Recyclerview未显示列表项。

7
在将数据集设置到适配器之前,我从Room数据库中获取数据集,然后将数据设置到适配器并将适配器设置到RecyclerView。目前列表中有2个项目。从我的日志中可以看出,所有方法都被调用了列表中的第一个项目,但没有调用第二个项目,并且没有任何项目或视图显示在屏幕上。我不确定发生了什么,能否有人帮助我找出问题?感谢您的帮助。
 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:clickable="true"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/goals_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutManager="LinearLayoutManager"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="1px"
        android:visibility="gone"
        />

    <!--view to show if the dataset is empty-->
    <TextView
        android:id="@+id/emptyElement"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:visibility="visible"
        android:text="No Goals Added"
        android:textColor="#525252"
        android:textSize="19sp"/>
</LinearLayout>

GoalsActivity.java

GoalsRecyclerViewAdapter adapter;
RecyclerView goalsListView;
....

goalsListView = (RecyclerView) findViewById(R.id.goals_list);

....

private void createGoalsList() {

        new AsyncTask<Void, Void, List<Goal>>(){

            @Override
            protected List<Goal> doInBackground(Void... params) {
                List<Goal> returnedGoals = goalDao.getAllGoals();
                return returnedGoals;
            }

            @Override
            protected void onPostExecute(List<Goal> returnedGoals) {

                //check your goals list is empty or not
                if(returnedGoals.size() > 0){

                    //make the goals list visible if there is data
                    goalsListView.setVisibility(View.VISIBLE);
                    noGoalsTxt.setVisibility(View.GONE);

                    //set array adapter for the goals list
                    adapter = new GoalsRecyclerViewAdapter(returnedGoals);
                    goalsListView.setAdapter(adapter);
                }else{

                    //if there is no data display empty list text.
                    goalsListView.setVisibility(View.GONE);
                    noGoalsTxt.setVisibility(View.VISIBLE);
                }
            }
        }.execute();
    }

GoalsRecyclerviewAdapter.java

public class GoalsRecyclerViewAdapter extends RecyclerView.Adapter<GoalsRecyclerViewAdapter.GoalsViewHolder> {

    private static final String TAG = GoalsRecyclerViewAdapter.class.getSimpleName();

    private List<Goal> mGoals;

    public GoalsRecyclerViewAdapter(List<Goal> goals) {
        Log.d(TAG, "adapter initialized");
        mGoals = goals;
    }

    @Override
    public GoalsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        Log.d(TAG, "onCreateViewHolder: inside");
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.goal_row, parent, false);
        return new GoalsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(GoalsViewHolder holder, int position) {

        Log.d(TAG, "onBindViewHolder: position " + position);
        holder.bind(mGoals.get(position));
    }

    @Override
    public int getItemCount() {
        Log.d(TAG, "getItemCount: " + mGoals.size());
        return mGoals.size();
    }

    class GoalsViewHolder extends RecyclerView.ViewHolder {

        TextView goalsLabel, goalCount;

        GoalsViewHolder(View itemView) {
            super(itemView);
            goalsLabel = (TextView) itemView.findViewById(R.id.calls_goal_label);
            goalCount = (TextView) itemView.findViewById(R.id.goal_count);
        }

        void bind(Goal goal){
            Log.d(TAG, "bind: " + goal.toString());
            goalsLabel.setText(goal.getGoalTitle());
            goalCount.setText(String.valueOf(goal.getGoalTarget()));
        }
    }

    public List<Goal> getGoals(){
        return mGoals;
    }

    public void setGoals(List<Goal> goals){
        mGoals = goals;
    }
}

更新:添加了行布局 goal_row.xml

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.ubcma.leadster.activity.GoalsActivity"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <TextView
        android:id="@+id/calls_goal_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="23sp"
        android:layout_alignParentLeft="true"
        android:layout_margin="@dimen/text_margin"
        tools:text="@string/calls_per_week"/>

    <TextView
        android:id="@+id/goal_count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_margin="@dimen/text_margin"
        android:textSize="23sp"
        tools:text="4"/>

</RelativeLayout>

日志

09-27 23:10:08.071 1606-1818/? D/ActivityManager: resumeTopActivityInnerLocked() : #1 prevTask=TaskRecord{46a33bdd0 #6227 A=com.ubcma.leadster U=0 StackId=1 sz=2} next=ActivityRecord{8396555d0 u0 com.ubcma.leadster/.activity.GoalsActivity t6227} mFocusedStack=ActivityStack{43432a4d0 stackId=1, 38 tasks}
09-27 23:10:08.128 24667-24667/com.ubcma.leadster D/ViewRootImpl@14dce6f[GoalsActivity]: setView = DecorView@be0e77c[GoalsActivity] touchMode=true
09-27 23:10:08.211 1606-4253/? D/WindowManager: finishDrawingWindow: Window{94ca436d0 u0 com.ubcma.leadster/com.ubcma.leadster.activity.GoalsActivity} mDrawState=DRAW_PENDING
09-27 23:10:08.213 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: adapter initialized
09-27 23:10:08.214 24667-24667/com.ubcma.leadster D/ViewRootImpl@14dce6f[GoalsActivity]: MSG_RESIZED_REPORT: ci=Rect(0, 72 - 0, 0) vi=Rect(0, 72 - 0, 0) or=1
09-27 23:10:08.214 24667-24667/com.ubcma.leadster D/ViewRootImpl@14dce6f[GoalsActivity]: MSG_WINDOW_FOCUS_CHANGED 1
09-27 23:10:08.225 1606-1917/? I/ActivityManager: Displayed com.ubcma.leadster/.activity.GoalsActivity: +153ms
09-27 23:10:08.229 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: getItemCount: 2
09-27 23:10:08.229 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: getItemCount: 2
09-27 23:10:08.230 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: getItemCount: 2
09-27 23:10:08.230 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: onCreateViewHolder: inside
09-27 23:10:08.233 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: onBindViewHolder: position 0
09-27 23:10:08.234 24667-24667/com.ubcma.leadster D/GoalsRecyclerViewAdapter: bind: Goal{id=1, goalType='r', goalTitle='Recruit', goalFrequency='Month', goalTarget=12}
09-27 23:10:08.247 1606-12625/? D/WindowManager: finishDrawingWindow: Window{94ca436d0 u0 com.ubcma.leadster/com.ubcma.leadster.activity.GoalsActivity} mDrawState=HAS_DRAWN

我对layout_height设置为match_parent有所疑虑,你是否尝试通过将背景颜色设置为相对布局来检查该项是否显示? - diedu
@diedu 在为相对布局添加背景颜色后,我发现该项的视图占据了整个屏幕。在RecyclerView中,如何知道何时使用wrap_content或match_parent?这真的很难判断,尤其是在嵌套子视图中。 - androgirl
为什么要添加这个 app:layout_behavior="@string/appbar_scrolling_view_behavior"? - Asad Mukhtar
4个回答

19

在设置RecyclerView的适配器之前,您需要先指定布局管理器,方法如下:

LinearLayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(mLayoutManager);

或者在布局中像以下这样指定:

app:layoutManager="android.support.v7.widget.LinearLayoutManager"

好的,但是也要尝试编程方式,并且有时从XML中删除可能会是问题所在。 - Dhaval Solanki

4

LayoutManager 是 RecyclerView 最有趣的部分。这个对象告诉 RecyclerView 何时回收已经移出屏幕并且可以去哪里的对象,而以前这完全由 ListView 完成。这个功能已经从 RecyclerView 中分离出来,以允许使用各种布局:垂直、水平、网格、分段或者您自己定义的布局!

LinearLayoutManager 将对象排列成类似于常规 ListView 的方式。

GridLayoutManager 像 GridView 一样以网格样式排列对象。

StaggeredGridLayoutManager 以交错网格格式排列项目。

您可以像以下示例那样添加 layoutmanager

Kotlin

var linearLayoutManager = LinearLayoutManager(this)
recycler.layoutManager = linearLayoutManager

Java

    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    recycler.setLayoutManager(linearLayoutManager);

4

将Recycler视图项的高度保持为match_parent仅显示一个视图屏幕。请将Recycler视图项的高度从match_parent更改为wrap_content。

还要删除app:layout_behavior="@string/appbar_scrolling_view_behavior"。

请查看此更新代码。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
    android:id="@+id/calls_goal_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="23sp"
    android:layout_alignParentLeft="true"
    android:layout_margin="20dp"
    android:text="sample"
/>

<TextView
    android:id="@+id/goal_count"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_margin="20dp"
    android:textSize="23sp"
    tools:text="4"/>


如果屏幕上只显示一个项目,那么我至少应该看到标签textview吧? - androgirl
1
天啊,就这样了。你能解释一下为什么它占据了整个屏幕吗?我以为高度只是视图本身的高度。 - androgirl
1
是的,视图本身的高度会导致问题,因为您将其设置为match_parent,这会导致每个Recycler View项占据整个屏幕...另外,app:layout_behavior="@string/appbar_scrolling_view_behavior" 这段代码是不必要的。 - Sharath kumar

3
在您的RecyclerView xml代码中设置 android:visibility="visible"。
更改:
<android.support.v7.widget.RecyclerView
    android:id="@+id/goals_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutManager="LinearLayoutManager"
    android:divider="@android:color/darker_gray"
    android:dividerHeight="1px"
    android:visibility="gone"
    />

To

<android.support.v7.widget.RecyclerView
    android:id="@+id/goals_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutManager="LinearLayoutManager"
    android:divider="@android:color/darker_gray"
    android:dividerHeight="1px"
    android:visibility="visible"
    />

编辑

将layoutManager添加到代码中。

goalsListView.setLayoutManager(new LinearLayoutManager(this));

请在xml代码中删除app:layoutManager="LinearLayoutManager"

如果列表中有数据,RecyclerView 将被设置为可见;如果没有数据,则将显示 TextView。 - androgirl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接