RecycleBin 是为了便于界面的复用而产生的类。大体而言 RecycleBin 的存储内容可分为两种类型:ActiveViews 和 ScrapViews。ActiveViews 是在屏幕上显示的 View,在显示结束后,所有的 ActiveView 都会被降级成为 ScrapViews。ScrapViews 是那些不在屏幕上显示,但又很可能被使用的 View,放在这里防止被回收,避免不必要的内存分配。
ActiveViews 中存储的第一个 view,它在列表中的位置
private int mFirstActivePosition;
在屏幕上展示的视图。视图一开始会在这个列表中,但在展示过程结束后就会移入 mScrapViews。列表中的视图是连续的,第一个视图的位置存储在 mFirstActivePosition 中
private View[] mActiveViews = new View[0];
可以用作 adapter 的转换 view,未排序
private ArrayList<View>[] mScrapViews;
视图类型数,mScrapViews 会对每个不同的视图类型分别做缓存
private int mViewTypeCount;
当前的回收视图
private ArrayList<View> mCurrentScrap;
由于某种原因,在应当回收时没有被回收的视图
private ArrayList<View> mSkippedScrap;
private SparseArray<View> mTransientStateViews;
private LongSparseArray<View> mTransientStateViewsById;
设置视图类型数,并初始化 mViewTypeCount、mCurrentScrap、mScrapViews,其中 mCurrentScrap 会被初始化为第一种类型的视图
public void setViewTypeCount(int viewTypeCount)
强制重绘所有视图,包括 mScrapViews、mTransientStateViews 和 mTransientStateViewsById 中的
public void markChildrenDirty()
当viewType大于等于0时返回true
public boolean shouldRecycleViewType(int viewType)
清空 scrap 堆,包括 mScrapViews、mTransientStateViews 和 mTransientStateViewsById
void clear()
用 AbsListView 的子 View 填充 ActiveViews。
在这里,mActiveViews 的空间若不足以放下 childCount 数目的 view,则会扩展空间。
会更新 mFirstActivePosition
更新每个 AbsListView 的子 view(getChildAt(i))的 LayoutParams,将其添加入 mActiveViews,并且记录每个子 view 的 scrappedFromPosition = firstActivePosition + i
header 和 footer 并不会被回收至 scrapViews
void fillActiveViews(int childCount, int firstActivePosition)
获取对应位置的视图。
如果在 mActiveViews 中,则:
final View match = activeViews[index];
activeViews[index] = null;
return match;
View getActiveView(int position)
获取缓存的视图,同上,获取之后也会清空视图列表里的视图
会先通过 mAdapter.getItemId(position) 中的 id 来从 mTransientStateViewsById 中获取
未命中则从 mTransientStateViews 来通过 position 获取
View getTransientStateView(int position)
清空缓存的视图
void clearTransientStateViews()
获取 ScrapView 中的视图,这些视图并不会排序
View getScrapView(int position)
将一个视图放在 Scrap 列表里
如果列表数据未变,或者 adapter 拥有固定的 ID (stable IDs),那么视图就会被保存,用于之后的使用
本方法不会回收 header 或 footer view,或其他不应当被回收的 view
回收时虽然已经不再显示该视图,但会避免触发类似 onDetached 等类似数据变化的回调
在转换状态中的视图不会被回收(scrap.hasTransientState()),所谓转换状态,例如动画中,用户正在选择点击等
其余的视图均会被放入列表中
void addScrapView(View scrap, int position)
清空所有跳过回收步骤的应当回收的视图
void removeSkippedScrap()
将所有活跃的视图移到回收列表中
同样对处于转换状态的视图不会被立即回收,而是放入缓存中(scrap.hasTransientState())
也不会回收 header 和 footer
void scrapActiveViews()
删除不在缓存区的被回收的所有视图(removeDetachedView(view, false))。
应当注意的是,需要确保释放的视图小于mActiveViews.size(),这种情况会出现在当adapter并没有回收它的视图时出现
也会删除缓存当中的视图
private void pruneScrapViews()
再利用处于回收队列的视图,获取所有的处于回收队列的视图
void reclaimScrapViews(List<View> views)
更新缓存中视图的颜色提示,对mScrapViews和mActiveViews中的视图均调用 view.setDrawingCacheBackgroundColor(color)
void setCacheColorHint(int color)
private View retrieveFromScrap(ArrayList<View> scrapViews, int position)
private void clearScrap(final ArrayList<View> scrap)
private void clearAccessibilityFromScrap(View view)
private void removeDetachedView(View child, boolean animate)