Recycleview相比也是每个Android开发者熟得不能再熟的控件了,但是你对他又真的了解多少呢?看看今天的三问你都能答得上来吗?
Recycleview布局效果更多,增加了纵向,表格,瀑布流等效果Recycleview去掉了一些api,比如setEmptyview,onItemClickListener等等,给到用户更多的自定义可能Recycleview去掉了设置头部底部item的功能,专向通过viewholder的不同type实现Recycleview实现了一些局部刷新,比如notifyitemchangedRecycleview自带了一些布局变化的动画效果,也可以通过自定义ItemAnimator类实现自定义动画效果Recycleview缓存机制更全面,增加两级缓存,还支持自定义缓存逻辑Recycleview有四级缓存,分别是mAttachedScrap(屏幕内),mCacheViews(屏幕外),mViewCacheExtension(自定义缓存),mRecyclerPool(缓存池)
mAttachedScrap(屏幕内),用于屏幕内itemview快速重用,不需要重新createView和bindViewmCacheViews(屏幕外),保存最近移出屏幕的ViewHolder,包含数据和position信息,复用时必须是相同位置的ViewHolder才能复用,应用场景在那些需要来回滑动的列表中,当往回滑动时,能直接复用ViewHolder数据,不需要重新bindView。mViewCacheExtension(自定义缓存),不直接使用,需要用户自定义实现,默认不实现。mRecyclerPool(缓存池),当cacheView满了后或者adapter被更换,将cacheView中移出的ViewHolder放到Pool中,放之前会把ViewHolder数据清除掉,所以复用时需要重新bindView。四级缓存按照顺序需要依次读取。所以完整缓存流程是:
itemView时,先把屏幕内的ViewHolder保存至AttachedScrap中CacheView,CacheView大小默认是2,超过数量的话按照先入先出原则,移出头部的itemview保存到RecyclerPool缓存池(如果有自定义缓存就会保存到自定义缓存里),RecyclerPool缓存池会按照itemview的itemtype进行保存,每个itemTyep缓存个数为5个,超过就会被回收。CacheView中获取,也是通过pos获取holder缓存 ——>获取失败,从自定义缓存中获取缓存——>获取失败,从mRecyclerPool中获取 ——>获取失败,重新创建viewholder——createViewHolder并bindview。需要注意的是,如果从缓存池找到缓存,还需要重新bindview。
bindViewHolder方法是在UI线程进行的,此方法不能耗时操作,不然将会影响滑动流畅性。比如进行日期的格式化。diffutil进行局部刷新,少用全局刷新itemVIew进行布局优化,比如少嵌套等。Prefetch 功能,也就是预取功能,嵌套时且使用的是LinearLayoutManager,子RecyclerView可通过setInitialPrefatchItemCount设置预取个数RecyclerView缓存,比如cacheview大小默认为2,可以设置大点,用空间来换取时间,提高流畅度setHasFixedSize(true)来避免requestLayout浪费资源,否则每次更新数据都会重新测量高度。void onItemsInsertedOrRemoved() {
if (hasFixedSize) layoutChildren();
else requestLayout();
}
RecycledView 的 Adapter 是一样的,比如嵌套的 RecyclerView 中存在一样的 Adapter,可以通过设置 RecyclerView.setRecycledViewPool(pool);来共用一个 RecycledViewPool。这样就减少了创建VIewholder的开销。getExtraLayoutSpace方法即可。new LinearLayoutManager(this) {
@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
return size;
}
};
RecyclerView.addOnScrollListener();来在滑动过程中停止加载的操作。CreateView里面去创建监听,因为CreateView调用要少于bindview。这样就减少了对象创建所造成的消耗notifyDataSetChange时,适配器不知道整个数据集中的那些内容以及存在,再重新匹配ViewHolder时会花生闪烁。设置adapter.setHasStableIds(true),并重写getItemId()来给每个Item一个唯一的ID,也就是唯一标识,就使itemview的焦点固定,解决了闪烁问题。