onCreateViewHolder of RecyclerView.Adapter is called twice or more, multiple times

回眸只為那壹抹淺笑 提交于 2019-12-01 13:58:19

问题


I'm currently developing an application which uses RecyclerView.

On reviewing LogCat I noticed that onCreateViewHolder was called twice after it was instantiated.

09-22 05:22:55.209 V/Adapter﹕ Construct
09-22 05:22:55.213 V/Adapter﹕ onCreateViewHolder
09-22 05:22:55.224 V/Adapter﹕ onBindViewHolder
09-22 05:22:55.240 V/Adapter﹕ onCreateViewHolder
09-22 05:22:55.247 V/Adapter﹕ onBindViewHolder

Also onBindViewHolder was called twice though I know it is called whenever the items are recycled.

But I think for onCreateViewHolder it is sufficient to be called once.

Is this abnormal behavior? If so, how can it be fixed?


回答1:


It's not abnormal but quite normal behavior. You don't have to worry.

It is true that a ViewHolder will be recycled and won't be re-created again.

However, multiple ViewHolders are needed to display multiple items on the app's screen. So there will a certain numbers of ViewHolders are created and for that onCreateViewHolder is called a certain times.

And onBindViewHolder will be called infinitly whenever data is reset to one of ViewHolders.

I examined this fact with test application like below:

MainActivity:

public class MainActivity extends AppCompatActivity {
    private static final String[] DATASET = new String[]{
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
            "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        MyAdapter myAdapter = new MyAdapter(DATASET);
        recyclerView.setAdapter(myAdapter);
    }
}

MyAdapter:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private static final String LOG_TAG = "RecyclerViewAdapter";
    private String[] dataset;

    private int counterOnCreateViewHolder = 0;
    private int counterOnBindViewHolder = 0;

    public MyAdapter(String[] dataset) {
        Log.d(LOG_TAG, "Construct");
        this.dataset = dataset;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView textView;
        public ViewHolder(TextView textView) {
            super(textView);
            this.textView = textView;
        }
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d(LOG_TAG, "onCreateViewHolder (" + ++counterOnCreateViewHolder + ")");
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.adapter_textview, parent, false);

        ViewHolder viewHolder = new ViewHolder((TextView) view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Log.d(LOG_TAG, "onBindViewHolder (" + ++counterOnBindViewHolder + ")");
        holder.textView.setText(dataset[position]);
    }

    @Override
    public int getItemCount() {
        // Log.d(LOG_TAG, "getItemCount");
        return dataset.length;
    }
}

layout/activity_main.xml:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"
    android:id="@+id/recycler_view" />

layout/adapter_textview.xml:

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/adapter_textview"
    android:textSize="30sp" />

Result:

09-22 06:03:04.166 D/RecyclerViewAdapter﹕ Construct
09-22 06:03:05.179 D/RecyclerViewAdapter﹕ onCreateViewHolder (1)
09-22 06:03:05.183 D/RecyclerViewAdapter﹕ onBindViewHolder (1)
09-22 06:03:05.190 D/RecyclerViewAdapter﹕ onCreateViewHolder (2)
09-22 06:03:05.192 D/RecyclerViewAdapter﹕ onBindViewHolder (2)
09-22 06:03:05.192 D/RecyclerViewAdapter﹕ onCreateViewHolder (3)
09-22 06:03:05.194 D/RecyclerViewAdapter﹕ onBindViewHolder (3)
09-22 06:03:05.195 D/RecyclerViewAdapter﹕ onCreateViewHolder (4)
09-22 06:03:05.197 D/RecyclerViewAdapter﹕ onBindViewHolder (4)
09-22 06:03:05.198 D/RecyclerViewAdapter﹕ onCreateViewHolder (5)
09-22 06:03:05.199 D/RecyclerViewAdapter﹕ onBindViewHolder (5)
09-22 06:03:05.200 D/RecyclerViewAdapter﹕ onCreateViewHolder (6)
09-22 06:03:05.202 D/RecyclerViewAdapter﹕ onBindViewHolder (6)
09-22 06:03:05.203 D/RecyclerViewAdapter﹕ onCreateViewHolder (7)
09-22 06:03:05.204 D/RecyclerViewAdapter﹕ onBindViewHolder (7)
09-22 06:03:05.206 D/RecyclerViewAdapter﹕ onCreateViewHolder (8)
09-22 06:03:05.207 D/RecyclerViewAdapter﹕ onBindViewHolder (8)
09-22 06:03:05.209 D/RecyclerViewAdapter﹕ onCreateViewHolder (9)
09-22 06:03:05.211 D/RecyclerViewAdapter﹕ onBindViewHolder (9)
09-22 06:03:05.212 D/RecyclerViewAdapter﹕ onCreateViewHolder (10)
09-22 06:03:05.213 D/RecyclerViewAdapter﹕ onBindViewHolder (10)
09-22 06:03:05.215 D/RecyclerViewAdapter﹕ onCreateViewHolder (11)
09-22 06:03:05.217 D/RecyclerViewAdapter﹕ onBindViewHolder (11)
09-22 06:03:05.218 D/RecyclerViewAdapter﹕ onCreateViewHolder (12)
09-22 06:03:05.220 D/RecyclerViewAdapter﹕ onBindViewHolder (12)
09-22 06:03:55.048 D/RecyclerViewAdapter﹕ onCreateViewHolder (13)
09-22 06:03:55.050 D/RecyclerViewAdapter﹕ onBindViewHolder (13)
09-22 06:03:55.228 D/RecyclerViewAdapter﹕ onCreateViewHolder (14)
09-22 06:03:55.229 D/RecyclerViewAdapter﹕ onBindViewHolder (14)
09-22 06:03:55.230 D/RecyclerViewAdapter﹕ onCreateViewHolder (15)
09-22 06:03:55.231 D/RecyclerViewAdapter﹕ onBindViewHolder (15)
09-22 06:03:55.232 D/RecyclerViewAdapter﹕ onBindViewHolder (16)
09-22 06:03:55.232 D/RecyclerViewAdapter﹕ onBindViewHolder (17)
09-22 06:03:55.260 D/RecyclerViewAdapter﹕ onBindViewHolder (18)
09-22 06:03:55.276 D/RecyclerViewAdapter﹕ onBindViewHolder (19)
09-22 06:03:55.296 D/RecyclerViewAdapter﹕ onBindViewHolder (20)
09-22 06:03:55.310 D/RecyclerViewAdapter﹕ onBindViewHolder (21)

As you can see, only onBindViewHolder was called after onCreateViewHolder (15).




回答2:


Here is a stable answer to stable Views for RecyclerView

These below line help to consistent list data in recyclerview vertically In my vertical list having only 10 items which i don't want to rebind again. Each row having infinite horizontal RecyclerView list.

  1. mRecyclerview.getRecycledViewPool().setMaxRecycledViews(int viewtype,int itemsCount)

  2. mRecyclerview.setItemViewCacheSize(int itemsCount)

    Both method helps not to recycle vertical views. But if list is too large then it will cause you OOM error, So be carefull to implement it.

    Here 0 is viewType in Recyclerview adapter and 10 are the items count.
    
    mRecyclerview.getRecycledViewPool().setMaxRecycledViews(0, 10);
    mRecyclerview.setItemViewCacheSize(10);
    



回答3:


You can increase the RecycledViewPool count by this code. By default it have 5.

you can increase as per your need.

recyclerView.getRecycledViewPool().setMaxRecycledViews(0,50);//0 - your view type



来源:https://stackoverflow.com/questions/32704825/oncreateviewholder-of-recyclerview-adapter-is-called-twice-or-more-multiple-tim

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!