打开ListView源码查看ListView的继承结构,发现ListView是继承自AbsListView
ListView作为列表,可以显示成百上千个item。如果有多少数据,就创建多少个item,会占用很大内存,但是大多数item并没有显示在屏幕上,造成了内存浪费,所以移除屏幕的view就可以缓存起来,以便下次重用。ListView为我们提供了convertView,来复用view,这里介绍下ListView的缓存机制。
1. RecycleBin类
查看ListView源码并没有缓存的相关代码,那一定是在父类中了。查看AbsListView的成员变量,有个mRecycler,看注释:用来存储不使用的view,其将被下次layout的时候重新使用,以避免创建新的实例。
/**
* The data set used to store unused views that should be reused during the next layout
* to avoid creating new ones
*/
final RecycleBin mRecycler = new RecycleBin();
看下RecycleBin这个类型,点进去查看,原来RecycleBin是AbsListView的内部类。
RecycleBin:大意就是通过两级缓存来缓存view。(RecycleBin在layout的过程中便于view重用,RecycleBin有两级存储:ActiveViews和ScrapViews。ActiveViews存储的是layout开始的时候屏幕上那些view。layout结束后,所有ActiveViews中的view被移动到ScrapViews中。ScrapViews中的views是那些可能被adapter重新用到的view,以避免重新创建不必要的view。)
1.1 RecycleBin成员变量
贴出RecycleBin的成员变量
/**
* The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
* storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
* start of a layout. By construction, they are displaying current information. At the end of
* layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
* could potentially be used by the adapter to avoid allocating views unnecessarily.
*/
class RecycleBin {
private RecyclerListener mRecyclerListener;
/**
* The position of the first view stored in mActiveViews.
*/
private int mFirstActivePosition;
/**
* Views that were on screen at the start of layout. This array is populated at the start of
* layout, and at the end of layout all view in mActiveViews are moved to mScrapViews.
* Views in mActiveViews represent a contiguous range of Views, with position of the first
* view store in mFirstActivePosition.
*/
private View[] mActiveViews = new View[0];
/**
* Unsorted views that can be used by the adapter as a convert view.
*/
private ArrayList<View>[] mScrapViews;
private int mViewTypeCount;
private ArrayList<View> mCurrentScrap;
private ArrayList<View> mSkippedScrap;
private SparseArray<View> mTransientStateViews;
private LongSparseArray<View> mTransientStateViewsById;
}
mActiveViews:一级缓存,顾名思义活动等view,这些view是布局过程开始屏幕上的view。layout开始时这个数组被填充,layout结束,mActiveViews中的view移动到mScrapViews。mActiveViews代表了一个连续范围的views,其第一个view的位置存储在mFirstActivePosition变量中。
mScrapViews :二级缓存,顾名思义废弃的view,无序的被adapter的convertView使用的view的集合
mScrapViews是多个list组成的数组,数组的长度为viewTypeCount,每个item是个list,所以每个list缓存不同类型item布局的view,所以mScrapViews应该是下图的样子。
mCurrentScrap:是个List,当ListView的item布局只有一种的时候使用该变量缓存view。所以mCurrentScrap是个