https://www.jianshu.com/p/193fb966e954

一,背景
RecyclerView是谷歌官方出的一个用于大量数据展示的新控件,可以用来代替传统的ListView,更加强大和灵活。
最近,自己负责的业务,也遇到这样的一个问题,关于是否要将ListView替换为RecyclerView?
秉承着实事求是的作风,弄清楚RecyclerView是否有足够的吸引力替换掉ListView,我从性能这一角度出发,研究RecyclerView和ListView二者的缓存机制,并得到了一些较有益的”结论”,待我慢慢道来。
同时也希望能通过本文,让大家快速了解RecyclerView与ListView在缓存机制上的一些区别,在使用上也更加得心应手吧。
PS:相关知识: ListView与RecyclerView缓存机制原理大致相似,如下图所示:

 
 

过程中,离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取,只是ListView与RecyclerView的实现细节有差异.(这只是缓存使用的其中一个场景,还有如刷新等)
PPS:本文不贴出详细代码,结合源码食用更佳!
二. 正文
2.1 缓存机制对比

  1. 层级不同:
    RecyclerView比ListView多两级缓存,支持多个离屏ItemView缓存,支持开发者自定义缓存处理逻辑,支持所有RecyclerView共用同一个RecyclerViewPool(缓存池)。
    具体来说: ListView(两级缓存): 

     

    RecyclerView(四级缓存): 

     

    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获取缓存的流程:

    RecyclerView获取缓存的流程:

     
     

    1). RecyclerView中mCacheViews(屏幕外)获取缓存时,是通过匹配pos获取目标位置的缓存,这样做的好处是,当数据源数据不变的情况下,无须重新bindView:

     

     

    而同样是离屏缓存,ListView从mScrapViews根据pos获取相应的缓存,但是并没有直接使用,而是重新getView(即必定会重新bindView),相关代码如下:

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

2.2 局部刷新
由上文可知,RecyclerView的缓存机制确实更加完善,但还不算质的变化,RecyclerView更大的亮点在于提供了局部刷新的接口,通过局部刷新,就能避免调用许多无用的bindView.

 

(RecyclerView和ListView添加,移除Item效果对比)
结合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()流程图:

 
 
 

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

 
 

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

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

三.结论
在一些场景下,如界面初始化,滑动等,ListView和RecyclerView都能很好地工作,两者并没有很大的差异:

文章的开头便抛出了这样一个问题,微信Android客户端卡券模块,大部分UI都是以列表页的形式展示,实现方式为ListView,是否有必要将其替换成RecyclerView呢?

 
 

答案是否定的,从性能上看,RecyclerView并没有带来显著的提升,不需要频繁更新,暂不支持用动画,意味着RecyclerView优势也不太明显,没有太大的吸引力,ListView已经能很好地满足业务需求。
数据源频繁更新的场景,如弹幕:http://www.jianshu.com/p/2232a63442d6等RecyclerView的优势会非常明显;

进一步来讲,结论是: 列表页展示界面,需要支持动画,或者频繁更新,局部刷新,建议使用RecyclerView,更加强大完善,易扩展;其它情况(如微信卡包列表页)两者都OK,但ListView在使用上会更加方便,快捷。

四.参考资料

      1. ListView
        a. android-23源码  b. Android ListView工作原理解析,带你从源码的角度彻底理解:http://blog.csdn.net/guolin_blog/article/details/44996879   c. android自己动手写ListView学习其原理:http://blog.csdn.net/androiddevelop/article/details/8734255
      2. RecyclerView
        a. RecyclerView-v7-23.4.0源码   b. RecyclerView剖析:http://blog.csdn.net/qq_23012315/article/details/50807224   c. RecyclerView剖析:http://blog.csdn.net/qq_23012315/article/details/51096696

作者:庞哈哈哈12138
链接:https://www.jianshu.com/p/193fb966e954
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

ListView与RecyclerView对比浅析——缓存机制的更多相关文章

  1. 【腾讯Bugly干货分享】Android ListView与RecyclerView对比浅析--缓存机制

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d3e3ab10c62013697408 作者:黄宁源 一,背景 Recy ...

  2. [转]Android ListView 与 RecyclerView 对比浅析—缓存机制

    从源码角度剖析ListView 与 RecyclerView 缓存机制的不同 https://zhuanlan.zhihu.com/p/23339185 原文地址:http://dev.qq.com/ ...

  3. RecyclerView 源码分析(二) —— 缓存机制

    在前一篇文章 RecyclerView 源码分析(一) -- 绘制流程解析 介绍了 RecyclerView 的绘制流程,RecyclerView 通过将绘制流程从 View 中抽取出来,放到 Lay ...

  4. RecyclerView与ListView 对比浅析:缓存机制

    一. 背景 PS:相关知识:ListView与RecyclerView缓存机制原理大致相似,如下图所示: 滑动过程中,离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取, ...

  5. 从 ListView 到 RecyclerView 的用法浅析

    文章目录 要走好明天的路,必须记住昨天走过的路,思索今天正在走着的路. ListView,一种在垂直滚动列表中显示条目的视图:RecyclerView,一种在局限的窗口呈现大数据集合的灵活视图.Rec ...

  6. RecyclerView 缓存机制详解

    一 前言 RecyclerView据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView.GridView.RecyclerView可以用来代替传 ...

  7. ListView缓存机制踩过的坑

    ListView,GrildView使用时候经常会用到缓存机制,随意一搜,例子成千上万,但是讲解都是很一致,跟自己踩的坑很少有人讲解到. 测试 需求: GrildView 分三列显示,默认背景为白色, ...

  8. 自己定制ListView,上拉刷新和下拉刷新,加载网络图片,并且添加缓存机制。

    package com.lixu.listviewrefresh; import java.util.ArrayList; import java.util.HashMap; import java. ...

  9. 关于RecyclerView中Viewholder和View的缓存机制的探究

    关于RecyclerView中Viewholder和View的缓存机制的探究 http://www.cnblogs.com/littlepanpc/p/4241575.html

随机推荐

  1. excel 函数1

    1 函数的相对引用和绝对引用 1.1绝对引用,相对引用和混合引用 按住F4键可以相互切换 1.2 if and or函数 案例图片 =IF(C7>30000,"大商家",&q ...

  2. Linux设备驱动之IIO子系统——IIO框架数据读取

    IIO DATA ACCESS IIO数据获取 只有两种方法可以使用IIO框架访问数据; 通过sysf通道进行一次性捕获,或通过IIO字符设备进行连续模式(触发缓冲). One-shot captur ...

  3. 章节十、1-用ID和XPath、name定位元素

    一.在定位元素时需要HTML标签,HTML是超文本标记语言,我们打开web网页是看到的内容就是通过html语言来实现的,按键盘“F12”调用开发者选项后,“Elements”栏中显示的就是网页的HTM ...

  4. macos 安装sublime text 3,如何安装插件

    1. 上面的代码如下: import urllib.request,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1 ...

  5. Saltstack_使用指南07_远程执行-执行模块

    1. 主机规划 远程执行教程文档 https://docs.saltstack.com/en/latest/topics/tutorials/modules.html 所有模块文档 https://d ...

  6. docker容器日志收集方案(方案三 filebeat+journald本地日志收集)

    其实方案三和方案二日志采集套路一样,但是还是有点差别. 差别就在于日志格式如下: ​ 为了方便对比吧日志贴上来 Nov 16 10:51:58 localhost 939fe968a91d[4721] ...

  7. WPF中自定义标题栏时窗体最大化处理之WindowChrome

    注意: 本文方法基础是WindowChrome,而WindowChrome在.NET Framework 4.5之后才集成发布的.见:WindowChrome Class 在.NET Framewor ...

  8. Linux Collection:文本编辑问题

    PAS 删除文本中的^M标记 由于历史原因,不同操作系统使用不同的方式表示文件的换行符\n.现代计算机系统中的文件换行和早期的打字机有关,主要和两个控制符有关:line feed (LF) ,carr ...

  9. HTML之间互相传参

    如图所示,在index.html详情展示中给detailsPanel穿参数,在detailsPanel中获取到参数写ajax到后台获取json数据,那么如何在detailsPanel.html中获取传 ...

  10. 明天研究下jpa直接像django一样生成

    https://blog.csdn.net/yztezhl/article/details/79390714 自动生成 教程-- https://blog.csdn.net/mxjesse/artic ...