RecyclerView⾯试必问
RecyclerView是⾕歌官⽅出的⼀个⽤于⼤量数据展⽰的新控件,可以⽤来代替传统的ListView,更加强⼤和灵活。
同时也希望能通过本⽂,让⼤家快速了解RecyclerView与ListView在缓存机制上的⾯试。
ListView与RecyclerView缓存机制原理⼤致相似,如下图所⽰:
缺席审判
过程中,离屏的ItemView即被回收⾄缓存,⼊屏的ItemView则会优先从缓存中获取,只是ListView与Re
cyclerView的实现细节有差异.(这只是缓存使⽤的其中⼀个场景,还有如刷新等)
⽐较
1.1 缓存机制对⽐
1.1.1 腾讯⾯试RecyclerView缓存机制(RecyclerView与ListView有哪⼏层缓存机制)
RecyclerView⽐ListView多两级缓存,⽀持多个离ItemView缓存,⽀持开发者⾃定义缓存处理逻辑,⽀持所有RecyclerView共⽤同⼀个RecyclerViewPool(缓存池)。
具体来说: ListView(两级缓存):
RecyclerView(四级缓存):
1.1.2 腾讯⾯试RecyclerView缓存机制(RecyclerView与ListView这⼏层缓存机制有什么区别和相同点)
相同点
ListView和RecyclerView缓存机制基本⼀致:
mActiveViews和mAttachedScrap功能相似,意义在于快速重⽤屏幕上可见的列表项ItemView,⽽不需要重新createView和bindView;
mScrapView和mCachedViews + mReyclerViewPool功能相似,意义在于缓存离开屏幕的ItemView,⽬的是让即将进⼊屏幕的ItemView重⽤.
RecyclerView的优势在于a.mCacheViews的使⽤,可以做到屏幕外的列表项ItemView进⼊屏幕内时也⽆须bindView快速重⽤;
b.mRecyclerPool可以供多个RecyclerView共同使⽤,在特定场景下,如viewpaper+多个列表页下有优势.客观来说,RecyclerView
在特定场景下对ListView的缓存机制做了补强和完善。
教导主任工作总结不同点
RecyclerView缓存RecyclerView.ViewHolder,抽象可理解为: View + ViewHolder(避免每次createView时调⽤
findViewById) + flag(标识状态);
ListView缓存View。
贵都国际花城缓存不同,⼆者在缓存的使⽤上也略有差别,具体来说: ListView获取缓存的流程:
RecyclerView获取缓存的流程:
RecyclerView中mCacheViews(屏幕外)获取缓存时,是通过匹配pos获取⽬标位置的缓存,这样做的好处是,当数据源数据不变的情况下,⽆须重新bindView,⽽同样是离屏缓存,ListView从mScrapViews根据pos获取相应的缓存,但是并没有直接使⽤,⽽是重新getView(即必定会重新bindView),相关代码如下:
//AbsListView源码:line2345
暴腌//通过匹配pos从mScrapView中获取缓存
final View scrapView = ScrapView(position);
//⽆论是否成功都直接调⽤getView,导致必定会调⽤createView
党风廉政final View child = View(position, scrapView, this);
if (scrapView != null) {
if (child != scrapView) {
mRecycler.addScrapView(scrapView, position);
} el {
...
}
}
ListView中通过pos获取的是view,即pos–>view;
RecyclerView中通过pos获取的是viewholder,即pos –> (view,viewHolder,flag);
从流程图中可以看出,标志flag的作⽤是判断view是否需要重新bindView,这也是RecyclerView实现局部刷新的⼀个核⼼。
1.2缓存局部刷新
1.2.1 字节RecyclerView⾯试题(RecyclerView的局部刷新讲讲,和ListView区别是什么)
车厘子樱桃的区别
由上⽂可知,RecyclerView的缓存机制确实更加完善,但还不算质的变化,RecyclerView更⼤的亮点在于提供了局部刷新的接⼝,通过局部刷新,就能避免调⽤许多⽆⽤的bindView。
结合RecyclerView的缓存机制,看看局部刷新是如何实现的:
以RecyclerView中notifyItemRemoved(1)为例
最终会调⽤requestLayout(),使整个RecyclerView重新绘制,过程为: onMeasure()–>onLayout()–>onDraw()烤披萨的做法
其中,onLayout()为重点,分为三步:
校园春色故事dispathLayoutStep1():记录RecyclerView刷新前列表项ItemView的各种信息,如Top,Left,Bottom,Right,⽤于动画的相关计算;
dispathLayoutStep2():真正测量布局⼤⼩,位置,核⼼函数为layoutChildren();
dispathLayoutStep3():计算布局前后各个ItemView的状态,如Remove,Add,Move,Update等,如有必要执⾏相应的动画.
其中,layoutChildren()流程图: