Listview与RecyclerView对比浅析

2017-09-20  本文已影响0人  SDY_0656

RecyclerView和ListView都是用于加载大量数据的控件,RecyclerView作为listview的改进加强型,相对于ListView,RecyclerView做出了以下优化:
1,封装了viewholder,Listview需要自己写ViewHolder缓存,而RecyclerView已经帮我们实现了。
2,RecyclerView的缓存机制有了加强,ListView是2级缓存,而RecyclerView实现了4级缓存。
3,RecyclerView相对于ListView最大的加强是实现了局部刷新,这对于ListView需要刷新全部列表进步很多,特别适用于那些数据源经常发生改变的情况。
下面从缓存机制做出对比:
ListView和RecyclerView的缓存机制大致类似:

1.png

过程中,离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取,只是ListView与RecyclerView的实现细节有差异.(这只是缓存使用的其中一个场景,还有如刷新等)。
1,缓存机制不同
RecyclerView比ListView多两级缓存,支持多个离ItemView缓存,支持开发者自定义缓存处理逻辑,支持所有RecyclerView共用同一个RecyclerViewPool(缓存池)。

具体来说:
ListView(两级缓存):

2.png

RecyclerView(四级缓存):

3.jpg

ListView和RecyclerView缓存机制基本一致:

1). mActiveViews和mAttachedScrap功能相似,意义在于快速重用屏幕上可见的列表项ItemView,而不需要重新createView和bindView;

 2). mScrapView和mCachedViews + mReyclerViewPool功能相似,意义在于缓存离开屏幕的ItemView,目的是让即将进入屏幕的ItemView重用.

3). RecyclerView的优势在于a.mCacheViews的使用,可以做到屏幕外的列表项ItemView进入屏幕内时也无须bindView快速重用;b.mRecyclerPool可以供多个RecyclerView共同使用,在特定场景下,如viewpaper+多个列表页下有优势.客观来说,RecyclerView在特定场景下对ListView的缓存机制做了补强和完善。

2,缓存对象不同
1). RecyclerView缓存RecyclerView.ViewHolder,抽象可理解为:
View + ViewHolder(避免每次createView时调用findViewById) + flag(标识状态);
2). ListView缓存View。
缓存的获取也有不同:
ListView缓存获取流程:

4.jpg
 RecyclerView缓存获取流程:
5.jpg

ListView中通过pos获取的是view,即pos–>view;
RecyclerView中通过pos获取的是viewholder,即pos --> (view,viewHolder,flag);
从流程图中可以看出,标志flag的作用是判断view是否需要重新bindView,这也是RecyclerView实现局部刷新的一个核心。

RecyclerView的局部刷新功能:
RecyclerView更大的亮点在于提供了局部刷新的接口,通过局部刷新,就能避免调用许多无用的bindView。

7.gif

结合RecyclerView的缓存机制,看看局部刷新是如何实现的:
以RecyclerView中notifyItemRemoved(1)为例,最终会调用requestLayout(),使整个RecyclerView重新绘制,过程为:
onMeasure()–>onLayout()–>onDraw()

其中,onLayout()为重点,分为三步:

1)dispathLayoutStep1():记录RecyclerView刷新前列表项ItemView的各种信息,如Top,Left,Bottom,Right,用于动画的相关计算;
2)dispathLayoutStep2():真正测量布局大小,位置,核心函数为layoutChildren();
3)dispathLayoutStep3():计算布局前后各个ItemView的状态,如Remove,Add,Move,Update等,如有必要执行相应的动画。

其中,layoutChildren()流程图:

8.jpg 9.png

当调用notifyItemRemoved时,会对屏幕内ItemView做预处理,修改ItemView相应的pos以及flag(流程图中红色部分):

10.png

当调用fill()中RecyclerView.getViewForPosition(pos)时,RecyclerView通过对pos和flag的预处理,使得bindview只调用一次.

需要指出,ListView和RecyclerView最大的区别在于数据源改变时的缓存的处理逻辑,ListView是"一锅端",将所有的mActiveViews都移入了二级缓存mScrapViews,而RecyclerView则是更加灵活地对每个View修改标志位,区分是否重新bindView。

参考文章:https://dev.qq.com/topic/5811d3e3ab10c62013697408

上一篇下一篇

猜你喜欢

热点阅读