Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 369
hata Avatar asked Sep 21 '15 21:09

hata


People also ask

How many times onCreateViewHolder is called in RecyclerView?

By default it have 5. you can increase as per your need.

How many times onBindViewHolder called in RecyclerView?

1 Answer. Show activity on this post. Yes it is perfectly normal for a RecyclerView to call onBindViewHolder() multiple times. A RecyclerView only creates minimum number of Views needed to fill the screen.

How often is onBindViewHolder called?

However, in RecyclerView the onBindViewHolder gets called every time the ViewHolder is bound and the setOnClickListener will be triggered too. Therefore, setting a click listener in onCreateViewHolder which invokes only when a ViewHolder gets created is preferable.

What is onCreateViewHolder?

onCreateViewHolder only creates a new view holder when there are no existing view holders which the RecyclerView can reuse. So, for instance, if your RecyclerView can display 5 items at a time, it will create 5-6 ViewHolders , and then automatically reuse them, each time calling onBindViewHolder .


1 Answers

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).

like image 167
hata Avatar answered Oct 14 '22 08:10

hata