关于RecyclerView中Viewholder和View的缓存机制的探究

这个题目放在草稿箱里面许久了,一直没有动力提笔。趁现在公司人还没有来齐,工作量还不是很大,就挤出来时间来把它完善了。

我们知道,RecyclerView是经典的ListView的进化与升华,它比ListView更加灵活,但也因此引入了一定的复杂性。最新的v7支持包新添加了RecyclerView。

我们知道,ListView通过使用ViewHolder来提升性能。ViewHolder通过保存item中使用到的控件的引用来减少findViewById的调用,以此使ListView滑动得更加顺畅。但这种模式即使不使用也无妨。

对于还不是很熟悉RecyclerView的程序员,可以先从这两篇文章里面了解一下它的基本用法:

Android L新控件RecyclerView简介

RecyclerView和CardView简介

这里对RecyclerView的基本使用方式,就不再赘述,只讨论RecyclerView中的ViewHolder的缓存机制。其实它的缓存机制大致原理跟ListView是相似的,只是在具体的实现细节上面有些差异。对于这些RecyclerView的缓存机制,Android L新控件RecyclerView简介这篇文章的结尾进行了总结性的概括,这里讨论的内容要远比这篇简介的内容要复杂和多。

首先,我定义了三个不同的Adapter,里面分别对应了三种情况:item类型只有一种;item类型有两种;item类型有三种。里面均重写了onCreateViewHolder方法,用于记录生成的ViewHolder或者View的数目。内容可以从Log里面查询得到。三个Adapter的细节分别是:

  1 /**
  2  * @Title: MyRVAdapter.java
  3  * @Package com.example.recyclerviewtest.adapter
  4  * @Description: TODO
  5  * @author SilentKnight || happychinapc[at]gmail[dot]com
  6  * @date 2015 2015年1月22日 下午4:54:25
  7  * @version V1.0.0
  8  */
  9 package com.example.recyclerviewtest.adapter;
 10
 11 import java.util.List;
 12
 13 import android.content.Context;
 14 import android.support.v7.widget.RecyclerView;
 15 import android.util.Log;
 16 import android.view.LayoutInflater;
 17 import android.view.View;
 18 import android.view.ViewGroup;
 19 import android.view.View.OnClickListener;
 20 import android.widget.TextView;
 21 import android.widget.Toast;
 22
 23 import com.example.recyclerviewtest.R;
 24
 25 /**
 26  * @ClassName: MyRVAdapter
 27  * @Description: TODO
 28  * @author SilentKnight || [email protected]
 29  * @date 2015年1月22日 下午4:54:25
 30  *
 31  */
 32 public class MyRVAdapter extends RecyclerView.Adapter<MyRVAdapter.ViewHolder> {
 33     private static int COUNT_CACHE_VIEW = 0;
 34     private static final String ADAPTER_TAG = MyRVAdapter.class.getSimpleName();
 35     private List<String> dataSet;
 36     private Context context;
 37
 38     public MyRVAdapter(Context context, List<String> dataSet) {
 39         this.context = context;
 40         this.dataSet = dataSet;
 41     }
 42
 43     /*
 44      * (non-avadoc) <p>Title: getItemId</p> <p>Description: </p>
 45      *
 46      * @params @param position
 47      *
 48      * @params @return
 49      *
 50      * @overrided @see
 51      * android.support.v7.widget.RecyclerView.Adapter#getItemId(int)
 52      */
 53     @Override
 54     public long getItemId(int position) {
 55         // TODO Auto-generated method stub
 56         return position;
 57     }
 58
 59     /*
 60      * (non-avadoc) <p>Title: getItemCount</p> <p>Description: </p>
 61      *
 62      * @params @return
 63      *
 64      * @overrided @see
 65      * android.support.v7.widget.RecyclerView.Adapter#getItemCount()
 66      */
 67     @Override
 68     public int getItemCount() {
 69         // TODO Auto-generated method stub
 70         return dataSet.size();
 71     }
 72
 73     /*
 74      * (non-avadoc) <p>Title: onBindViewHolder</p> <p>Description: </p>
 75      *
 76      * @params @param arg0
 77      *
 78      * @params @param arg1
 79      *
 80      * @overrided @see
 81      * android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder
 82      * (android.support.v7.widget.RecyclerView.ViewHolder, int)
 83      */
 84     @Override
 85     public void onBindViewHolder(ViewHolder holder, final int arg1) {
 86         // TODO Auto-generated method stub
 87         holder.tv.setOnClickListener(new OnClickListener() {
 88
 89             @Override
 90             public void onClick(View v) {
 91                 // TODO Auto-generated method stub
 92                 Toast.makeText(context, "You clickd TextView at index of "+arg1,
 93                         Toast.LENGTH_SHORT).show();
 94             }
 95         });
 96         holder.tv.setText(dataSet.get(arg1));
 97     }
 98
 99     /*
100      * (non-avadoc) <p>Title: onCreateViewHolder</p> <p>Description: </p>
101      *
102      * @params @param arg0
103      *
104      * @params @param arg1
105      *
106      * @params @return
107      *
108      * @overrided @see
109      * android.support.v7.widget.RecyclerView.Adapter#onCreateViewHolder
110      * (android.view.ViewGroup, int)
111      */
112
113     @Override
114     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
115         // TODO Auto-generated method stub
116         Log.i(ADAPTER_TAG, "itemTV---" + ++COUNT_CACHE_VIEW);
117         View itemLayout = LayoutInflater.from(viewGroup.getContext()).inflate(
118                 R.layout.recycler_view_item_layout_tv, null);
119         return new ViewHolder(itemLayout);
120     }
121
122     public static class ViewHolder extends RecyclerView.ViewHolder {
123         public TextView tv;
124
125         /**
126          * <p>
127          * Title: MainActivity.java
128          * </p>
129          * <p>
130          * Description:
131          * </p>
132          *
133          * @param @param itemView
134          */
135         public ViewHolder(View itemView) {
136             super(itemView);
137             // TODO Auto-generated constructor stub
138             tv = (TextView) itemView.findViewById(R.id.rv_item_tv);
139         }
140     }
141 }

MyRVAdapter

  1 /**
  2  * @Title: MyRVAdapter2.java
  3  * @Package com.example.recyclerviewtest.adapter
  4  * @Description: TODO
  5  * @author SilentKnight || happychinapc[at]gmail[dot]com
  6  * @date 2015 2015年1月22日 下午4:55:31
  7  * @version V1.0.0
  8  */
  9 package com.example.recyclerviewtest.adapter;
 10
 11 import java.util.List;
 12
 13 import android.content.Context;
 14 import android.content.Intent;
 15 import android.support.v7.widget.RecyclerView;
 16 import android.util.Log;
 17 import android.view.LayoutInflater;
 18 import android.view.View;
 19 import android.view.ViewGroup;
 20 import android.view.View.OnClickListener;
 21 import android.widget.ImageView;
 22 import android.widget.TextView;
 23 import android.widget.Toast;
 24
 25 import com.example.recyclerviewtest.GridViewHorizontalTest;
 26 import com.example.recyclerviewtest.GridViewVerticalTest;
 27 import com.example.recyclerviewtest.R;
 28
 29 /**
 30  * @ClassName: MyRVAdapter2
 31  * @Description: TODO
 32  * @author SilentKnight || [email protected]
 33  * @date 2015年1月22日 下午4:55:31
 34  *
 35  */
 36 public class MyRVAdapter2 extends RecyclerView.Adapter<MyRVAdapter2.ViewHolder> {
 37     private static int COUNT_CACHE_VIEW_1 = 0;
 38     private static int COUNT_CACHE_VIEW_2 = 0;
 39     private static final String ADAPTER_TAG = MyRVAdapter2.class
 40             .getSimpleName();
 41     private static final int TYPE_TV = 0x000;
 42     private static final int TYPE_IV = 0x0001;
 43     private List<String> dataSet;
 44     private Context context;
 45
 46     public MyRVAdapter2(Context context, List<String> dataSet) {
 47         this.context = context;
 48         this.dataSet = dataSet;
 49     }
 50
 51     /*
 52      * (non-avadoc) <p>Title: getItemId</p> <p>Description: </p>
 53      *
 54      * @params @param position
 55      *
 56      * @params @return
 57      *
 58      * @overrided @see
 59      * android.support.v7.widget.RecyclerView.Adapter#getItemId(int)
 60      */
 61     @Override
 62     public long getItemId(int position) {
 63         // TODO Auto-generated method stub
 64         return position;
 65     }
 66
 67     /*
 68      * (non-avadoc) <p>Title: getItemViewType</p> <p>Description: </p>
 69      *
 70      * @params @param position
 71      *
 72      * @params @return
 73      *
 74      * @overrided @see
 75      * android.support.v7.widget.RecyclerView.Adapter#getItemViewType(int)
 76      */
 77     @Override
 78     public int getItemViewType(int position) {
 79         // TODO Auto-generated method stub
 80         if (position % 2 == 0) {
 81             return TYPE_TV;
 82         } else {
 83             return TYPE_IV;
 84         }
 85     }
 86
 87     /*
 88      * (non-avadoc) <p>Title: getItemCount</p> <p>Description: </p>
 89      *
 90      * @params @return
 91      *
 92      * @overrided @see
 93      * android.support.v7.widget.RecyclerView.Adapter#getItemCount()
 94      */
 95     @Override
 96     public int getItemCount() {
 97         // TODO Auto-generated method stub
 98         return dataSet.size();
 99     }
100
101     /*
102      * (non-avadoc) <p>Title: onBindViewHolder</p> <p>Description: </p>
103      *
104      * @params @param arg0
105      *
106      * @params @param arg1
107      *
108      * @overrided @see
109      * android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder
110      * (android.support.v7.widget.RecyclerView.ViewHolder, int)
111      */
112     @Override
113     public void onBindViewHolder(ViewHolder holder, int arg1) {
114         // TODO Auto-generated method stub
115         if (getItemViewType(arg1) == TYPE_TV) {
116             holder.tv.setOnClickListener(new OnClickListener() {
117
118                 @Override
119                 public void onClick(View v) {
120                     // TODO Auto-generated method stub
121                     context.startActivity(new Intent(context,
122                             GridViewHorizontalTest.class));
123                 }
124             });
125             holder.tv.setText(dataSet.get(arg1));
126         } else {
127             holder.iv.setOnClickListener(new OnClickListener() {
128
129                 @Override
130                 public void onClick(View v) {
131                     // TODO Auto-generated method stub
132                     context.startActivity(new Intent(context,
133                             GridViewVerticalTest.class));
134                 }
135             });
136         }
137     }
138
139     /*
140      * (non-avadoc) <p>Title: onCreateViewHolder</p> <p>Description: </p>
141      *
142      * @params @param arg0
143      *
144      * @params @param arg1
145      *
146      * @params @return
147      *
148      * @overrided @see
149      * android.support.v7.widget.RecyclerView.Adapter#onCreateViewHolder
150      * (android.view.ViewGroup, int)
151      */
152
153     @Override
154     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
155         // TODO Auto-generated method stub
156         if (getItemViewType(arg1) == TYPE_TV) {
157             Log.i(ADAPTER_TAG, "itemTV---" + ++COUNT_CACHE_VIEW_1);
158             View itemLayout = LayoutInflater.from(viewGroup.getContext())
159                     .inflate(R.layout.recycler_view_item_layout_tv, null);
160             return new ViewHolder(itemLayout, TYPE_TV);
161         } else {
162             Log.i(ADAPTER_TAG, "itemIV---" + ++COUNT_CACHE_VIEW_2);
163             View itemLayout = LayoutInflater.from(viewGroup.getContext())
164                     .inflate(R.layout.recycler_view_item_layout_iv, null);
165             return new ViewHolder(itemLayout, TYPE_IV);
166         }
167     }
168
169     public static class ViewHolder extends RecyclerView.ViewHolder {
170         public TextView tv;
171         public ImageView iv;
172
173         /**
174          * <p>
175          * Title: MainActivity.java
176          * </p>
177          * <p>
178          * Description:
179          * </p>
180          *
181          * @param @param itemView
182          */
183         public ViewHolder(View itemView, int itemType) {
184             super(itemView);
185             // TODO Auto-generated constructor stub
186             if (itemType == TYPE_TV) {
187                 tv = (TextView) itemView.findViewById(R.id.rv_item_tv);
188             } else {
189                 iv = (ImageView) itemView.findViewById(R.id.rv_item_iv);
190             }
191         }
192     }
193 }

MyRVAdapter2

  1 /**
  2  * @Title: MyRVAdapter3.java
  3  * @Package com.example.recyclerviewtest.adapter
  4  * @Description: TODO
  5  * @author SilentKnight || happychinapc[at]gmail[dot]com
  6  * @date 2015 2015年1月22日 下午4:56:33
  7  * @version V1.0.0
  8  */
  9 package com.example.recyclerviewtest.adapter;
 10
 11 import java.util.List;
 12
 13 import android.content.Context;
 14 import android.support.v7.widget.RecyclerView;
 15 import android.util.Log;
 16 import android.view.LayoutInflater;
 17 import android.view.View;
 18 import android.view.ViewGroup;
 19 import android.view.View.OnClickListener;
 20 import android.widget.ImageView;
 21 import android.widget.TextView;
 22 import android.widget.Toast;
 23
 24 import com.example.recyclerviewtest.R;
 25
 26 /**
 27  * @ClassName: MyRVAdapter3
 28  * @Description: TODO
 29  * @author SilentKnight || [email protected]
 30  * @date 2015年1月22日 下午4:56:33
 31  *
 32  */
 33 public class MyRVAdapter3 extends RecyclerView.Adapter<MyRVAdapter3.ViewHolder> {
 34     private static int COUNT_CACHE_VIEW_1 = 0;
 35     private static int COUNT_CACHE_VIEW_2 = 0;
 36     private static int COUNT_CACHE_VIEW_3 = 0;
 37     private static final String ADAPTER_TAG = MyRVAdapter3.class
 38             .getSimpleName();
 39     private static final int TYPE_TV = 0x000;
 40     private static final int TYPE_IV = 0x0001;
 41     private static final int TYPE_TV_2 = 0x0002;
 42     private List<String> dataSet;
 43     private Context context;
 44
 45     public MyRVAdapter3(Context context, List<String> dataSet) {
 46         this.context = context;
 47         this.dataSet = dataSet;
 48     }
 49
 50     /*
 51      * (non-avadoc) <p>Title: getItemId</p> <p>Description: </p>
 52      *
 53      * @params @param position
 54      *
 55      * @params @return
 56      *
 57      * @overrided @see
 58      * android.support.v7.widget.RecyclerView.Adapter#getItemId(int)
 59      */
 60     @Override
 61     public long getItemId(int position) {
 62         // TODO Auto-generated method stub
 63         return position;
 64     }
 65
 66     /*
 67      * (non-avadoc) <p>Title: getItemViewType</p> <p>Description: </p>
 68      *
 69      * @params @param position
 70      *
 71      * @params @return
 72      *
 73      * @overrided @see
 74      * android.support.v7.widget.RecyclerView.Adapter#getItemViewType(int)
 75      */
 76     @Override
 77     public int getItemViewType(int position) {
 78         // TODO Auto-generated method stub
 79         if (position % 3 == 0) {
 80             return TYPE_TV;
 81         } else if (position % 3 == 1) {
 82             return TYPE_IV;
 83         } else {
 84             return TYPE_TV_2;
 85         }
 86     }
 87
 88     /*
 89      * (non-avadoc) <p>Title: getItemCount</p> <p>Description: </p>
 90      *
 91      * @params @return
 92      *
 93      * @overrided @see
 94      * android.support.v7.widget.RecyclerView.Adapter#getItemCount()
 95      */
 96     @Override
 97     public int getItemCount() {
 98         // TODO Auto-generated method stub
 99         return dataSet.size();
100     }
101
102     /*
103      * (non-avadoc) <p>Title: onBindViewHolder</p> <p>Description: </p>
104      *
105      * @params @param arg0
106      *
107      * @params @param arg1
108      *
109      * @overrided @see
110      * android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder
111      * (android.support.v7.widget.RecyclerView.ViewHolder, int)
112      */
113     @Override
114     public void onBindViewHolder(ViewHolder holder, int arg1) {
115         // TODO Auto-generated method stub
116         if (getItemViewType(arg1) == TYPE_TV) {
117             holder.tv.setOnClickListener(new OnClickListener() {
118
119                 @Override
120                 public void onClick(View v) {
121                     // TODO Auto-generated method stub
122                     Toast.makeText(context, "You clickd TextView",
123                             Toast.LENGTH_SHORT).show();
124                 }
125             });
126             holder.tv.setText(dataSet.get(arg1));
127         } else if (getItemViewType(arg1) == TYPE_IV) {
128             holder.iv.setOnClickListener(new OnClickListener() {
129
130                 @Override
131                 public void onClick(View v) {
132                     // TODO Auto-generated method stub
133
134                     Toast.makeText(context, "You clickd ImageView",
135                             Toast.LENGTH_SHORT).show();
136                 }
137             });
138         } else {
139
140         }
141     }
142
143     /*
144      * (non-avadoc) <p>Title: onCreateViewHolder</p> <p>Description: </p>
145      *
146      * @params @param arg0
147      *
148      * @params @param arg1
149      *
150      * @params @return
151      *
152      * @overrided @see
153      * android.support.v7.widget.RecyclerView.Adapter#onCreateViewHolder
154      * (android.view.ViewGroup, int)
155      */
156
157     @Override
158     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
159         // TODO Auto-generated method stub
160         if (getItemViewType(arg1) == TYPE_TV) {
161             Log.i(ADAPTER_TAG, "itemTV---" + ++COUNT_CACHE_VIEW_1);
162             View itemLayout = LayoutInflater.from(viewGroup.getContext())
163                     .inflate(R.layout.recycler_view_item_layout_tv, null);
164             return new ViewHolder(itemLayout, TYPE_TV);
165         } else if (getItemViewType(arg1) == TYPE_IV) {
166             Log.i(ADAPTER_TAG, "itemIV---" + ++COUNT_CACHE_VIEW_2);
167             View itemLayout = LayoutInflater.from(viewGroup.getContext())
168                     .inflate(R.layout.recycler_view_item_layout_iv, null);
169             return new ViewHolder(itemLayout, TYPE_IV);
170         } else {
171             Log.i(ADAPTER_TAG, "itemTV2---" + ++COUNT_CACHE_VIEW_3);
172             View itemLayout = LayoutInflater.from(viewGroup.getContext())
173                     .inflate(R.layout.recycler_view_item_layout_tv_2, null);
174             return new ViewHolder(itemLayout, TYPE_TV_2);
175         }
176     }
177
178     public static class ViewHolder extends RecyclerView.ViewHolder {
179         public TextView tv;
180         public TextView tv2;
181         public ImageView iv;
182
183         /**
184          * <p>
185          * Title: MainActivity.java
186          * </p>
187          * <p>
188          * Description:
189          * </p>
190          *
191          * @param @param itemView
192          */
193         public ViewHolder(View itemView, int itemType) {
194             super(itemView);
195             // TODO Auto-generated constructor stub
196             if (itemType == TYPE_TV) {
197                 tv = (TextView) itemView.findViewById(R.id.rv_item_tv);
198             } else if (itemType == TYPE_IV) {
199                 iv = (ImageView) itemView.findViewById(R.id.rv_item_iv);
200             } else {
201                 tv2 = (TextView) itemView.findViewById(R.id.rv_item_tv);
202             }
203         }
204     }
205 }

MyRVAdapter3

同时,这个测试工程里面只有一个Activity,它的详情如下:

 1 package com.example.recyclerviewtest;
 2
 3 import java.util.List;
 4
 5 import com.example.recyclerviewtest.adapter.MyRVAdapter;
 6 import com.example.recyclerviewtest.adapter.MyRVAdapter2;
 7 import com.example.recyclerviewtest.adapter.MyRVAdapter3;
 8 import com.example.recyclerviewtest.util.Utils;
 9
10 import android.support.v7.app.ActionBarActivity;
11 import android.support.v7.widget.LinearLayoutManager;
12 import android.support.v7.widget.RecyclerView;
13 import android.os.Bundle;
14 import android.widget.LinearLayout;
15
16 public class MainActivity extends ActionBarActivity {
17     private static final String TAG = MainActivity.class.getSimpleName();
18
19     private RecyclerView rvHorizontal;
20     private RecyclerView rvVertical;
21
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_main);
26         rvHorizontal = (RecyclerView) findViewById(R.id.recyclier_view_horizontal);
27         rvVertical = (RecyclerView) findViewById(R.id.recyclier_view_vertical);
28         List<String> dataSet = Utils.generateDataSet();
29         LinearLayoutManager layoutManager = new LinearLayoutManager(this,
30                 LinearLayout.HORIZONTAL, false);
31         rvHorizontal.setLayoutManager(layoutManager);
32         layoutManager = new LinearLayoutManager(this, LinearLayout.VERTICAL,
33                 false);
34         rvVertical.setLayoutManager(layoutManager);
35         MyRVAdapter adapter = new MyRVAdapter(this, dataSet);
36         MyRVAdapter2 adapter2 = new MyRVAdapter2(this, dataSet);
37         MyRVAdapter3 adapter3 = new MyRVAdapter3(this, dataSet);
38         rvHorizontal.setAdapter(adapter2);
39         rvVertical.setAdapter(adapter);
40     }
41
42 }

MainActivity

对于你想测试的三种情况,你可以通达代码rvHorizontal.setAdapter(adapter2)和rvVertical.setAdapter(adapter)来进行测试。在测试的过程中,可以通过改变RecyclerView的宽度来测试显示ViewHolder的数目。比如,item的宽度为60dp,你可以分别测试下RecyclerView的宽度分别为60dp、120dp和180dp情况下log的打印情况。其中,activity的布局文件如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.example.recyclerviewtest.MainActivity" >
10
11     <android.support.v7.widget.RecyclerView
12         android:id="@+id/recyclier_view_horizontal"
13         android:layout_width="240dp"
14         android:layout_height="70dp"
15         android:layout_alignParentTop="true"
16         android:layout_centerHorizontal="true"
17         android:scrollbars="horizontal" >
18     </android.support.v7.widget.RecyclerView>
19
20     <android.support.v7.widget.RecyclerView
21         android:id="@+id/recyclier_view_vertical"
22         android:layout_width="match_parent"
23         android:layout_height="360dp"
24         android:layout_below="@id/recyclier_view_horizontal"
25         android:layout_centerHorizontal="true"
26         android:scrollbars="vertical" >
27     </android.support.v7.widget.RecyclerView>
28
29 </RelativeLayout>

activity_main.xml

其中一个item的布局如下:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:gravity="center"
 6     android:orientation="vertical" >
 7
 8     <TextView
 9         android:id="@+id/rv_item_tv"
10         android:layout_width="60dp"
11         android:layout_height="20dp"
12         android:layout_gravity="center"
13         android:background="@drawable/item_selector"
14         android:clickable="true"
15         android:focusable="true"
16         android:focusableInTouchMode="true"
17         android:gravity="center" >
18     </TextView>
19
20 </LinearLayout>

recycler_view_item_layout_tv.xml

总之,测试的结论是这样的:在只有一种item的情况下,缓存的ViewHolder的数目为RecyclerView在滑动过程中所能在一屏内容纳的最大item个数+2。比如,在一个屏幕中只有item A可以显示,在滑动的过程最多可以出现6个item(这个最多是指所有item的个数,包括显示完全和显示不完全的总数),那么ViewHolder的缓存个数将会是8;而有至少两种item显示的情况下,每种item的ViewHolder的缓存个数为单种item在一屏内最大显示个数+1;比如,有3种item A,B,C,在滑动的过程,item A最多的情况下一屏显示了2个,那个item A对应的ViewHolder的缓存个数就是3个。

工程源文件可以从下面的链接打开下载。

点击下载源码

时间: 2024-08-24 12:31:08

关于RecyclerView中Viewholder和View的缓存机制的探究的相关文章

RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题)

RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题) 对于使用ViewHolder引起的图片错乱问题,相信大部分人都有遇到过,我也一样,对于解决方法也有所了解,但一直都是知其然不知其所以然. 所以,这次直接把ViewHolder的工作原理,通过简单的demo代码来验证一次,验证后对于图片错乱和闪烁这种问题的成因就很清楚了. 下面先上一副图 这幅图就比较清晰的画出了ViewHolder的工作原理. 可以看到,图中左上角item1上面有一条蓝色的线,item7下面也有

WCF技术剖析之八:ClientBase&lt;T&gt;中对ChannelFactory&lt;T&gt;的缓存机制

原文:WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service Proxy).而ChannelFactory<T>则是服务代理的创建者.WCF采用基于终结点(Endpoint)服务消费方式:WCF服务通过一个或者多个终结点暴露给潜在的服务消费者,服务的消费中通过与之匹配的终结点与之交互.在客户端,我们具有两种典型的服务代理创建方式,其一是通过诸如SvcUti

Hibernate中的HQL查询与缓存机制

HQL:完全面向对象查询 SQL的执行顺序: 1.From 2.Where 过滤基础数据 where与having的区别:1.顺序不同 2.where过滤基础数据 3. 过滤聚合函数 3.Group by 4.Select 5.Having 6.Order by   使用Hibernate查询时,使用hibernate的一个接口query Hql是面向对象的查询语句,所以跟的是类名 Query query = session.createQuery("select id,name,stu.cla

ListView与RecyclerView对比浅析——缓存机制

https://www.jianshu.com/p/193fb966e954 一,背景 RecyclerView是谷歌官方出的一个用于大量数据展示的新控件,可以用来代替传统的ListView,更加强大和灵活. 最近,自己负责的业务,也遇到这样的一个问题,关于是否要将ListView替换为RecyclerView? 秉承着实事求是的作风,弄清楚RecyclerView是否有足够的吸引力替换掉ListView,我从性能这一角度出发,研究RecyclerView和ListView二者的缓存机制,并得到

《深入理解mybatis原理》 MyBatis缓存机制的设计与实现

本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存.二级缓存: 一级缓存是Session会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存.一级缓存是MyBatis内部实现的一个特性,用户不能配置,默认情况下自动支持的缓存,用户没有定制它的权利(不过这也不是绝对的,可以通过开发插件对它进行修改): 二级缓存是A

剖析OkHttp缓存机制

现在应用市场上的 App 无一不需要网络操作,这些应用的开发者大多数都选择结合使用 OkHttp 和 Retrofit 来完成网络操作.okHttp 最为人称道的一个特性就是它的缓存机制,而我将在本篇博文对其进行剖析. 每次我用 OkHttp 时我都需要一些时间想想我将怎么使用它,我该用哪一个 HTTP 报头,作为一个客户端 App 我有哪些职责,我期望从服务器上获得什么,等等……所以对我来说,这篇博文将是 OkHttp 缓存特性的引用文档,我写这篇文档不是因为我在之后的开发中可能会接触 OkH

《深入理解mybatis原理4》 MyBatis缓存机制的设计与实现

<深入理解mybatis原理> MyBatis缓存机制的设计与实现 本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存.二级缓存:   一级缓存是Session会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存.一级缓存是MyBatis内部实现的一个特性,用户不能配置,默认情况下自动支持的缓存,用户没有定制它

[Android]对BaseAdapter中ViewHolder编写简化(转)

来自博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html 在Android项目中,经常都会用到ListView这个控件,而相应的Adapter中getView()方法的编写有一个标准的形式,如下: 1 @Override 2 public View getView(int position, View convertView, ViewGroup parent) { 3 ViewHolder holder; 4 if(null == c

Android中ViewHolder模式开发的详细解释

Android开发中ViewHolder模式开发的详细解释: 1.ViewHolder的解释: (1).只是一个静态类,不是Android的API方法. (2).它的作用就在于减少不必要的调用findViewById,然后把对底下的控件引用存在ViewHolder里面,再在View.setTag(holder)把它放在view里,下次就可以直接取了. 2.convertView中的TAG: (1).Tag不像ID是用标示view的.Tag从本质上来讲是就是相关联的view的额外的信息.它们经常用