问题
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.
mRecyclerview.getRecycledViewPool().setMaxRecycledViews(int viewtype,int itemsCount)
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