聊聊android列表视图的缓存设计

我们都知道在手机应用中显示列表数据是最常见的一种使用场景,比如新闻、微博、朋友圈等,但是由于移动设备的性能有限(尤其是内存),当我们在绘制列表视图时不可能将成百上千条数据一下子全部绘制到界面上,否则在低配手机上必然会引起应用卡顿甚至OOM,从而导致应用体验很差。在这种情况下我们该如何对应用进行优化呢?android中提供了listview和recyclerview两个列表视图控件来支持大量数据在界面上的高效显示,他们的核心思想都是通过缓存来优化界面处理过程中的性能问题。那么接下来我们就简单分析下listview和recyclerview的缓存设计。

为什么需要缓存

前面提到移动设备存在性能瓶颈,假设我们在一个页面上要加载显示1000条数据,如果直接new 1000个view实例然后显示这种方式在低配手机上很可能会造成界面卡顿甚至OOM,而且由于手机的屏幕尺寸有限而且一般都比较小,用户在使用过程中只能同看到屏幕内的几个view,而其余的不可见的那些view,对于用户来说其实是“无用”的,那么view这里就是我们可以优化的一个点了。我们可以根据手机屏幕内最多可容纳的view个数来创建很少的view实例用于显示在界面上,然后再使用一个小容量的缓存来存储不可见的view实例方便复用,这样我们就可以大大的节省应用占用的内存空间,从而优化用户的体验。当然这种优化方式也是基于用户的特殊使用场景,如果换一个使用场景(假设屏幕无限大,当然这种场景实际是不存在的),那么这种方式其实就无效了,其实想说的就是,没有一种优化方案是万能的,每一种优化都只有在基于特定场景下才能发挥最大的作用。

基于缓存的android列表视图

android提供了listview和recyclerview来展示列表视图,他们都利用了之前提到的缓存设计思想来优化大数据量的加载和显示。listview在较早的android版本中就出现了,其使用了二级缓存来避免创建不必要的view实例,当然缓存设计的加入在改善了程序运行效率的同时也势必会增加程序逻辑处理的复杂度,但是相比性能的提升这种改造成本是值得的。recyclerview是在android5.0版本之后出现的,其采用了四级缓存设计,通常我们使用的都只有三级。相比listview,其对性能的优化粒度更细,因此保证了效率更高,加之其设计和使用上更加灵活,所以目前大部分开发者选择recyclerview来实现列表数据和展示。接来下分别对这两个控件的缓存设计进行分析,本文仅仅描述缓存设计思路不涉及源码分析,想要深入了解请查阅末尾的参考文档。

ListView的缓存设计


通常为了进一步提高效率,我们会在ListView的adapter内部定义一个ViewHolder,这个ViewHolder跟RecyclerView的ViewHolder有点类似。其内部会保存每个ItemView的childView,这样我们在使用复用的ItemView(其实也就是ConvertView)刷新数据时,不用重新调用findViewById来定位childView了,这样可以提高运行效率,因为findViewById也是会按照广度优先遍历ItemView下的子结点,如果itemView下的层级结构比较深,开销也不可忽视。

RecyclerView的缓存设计

ListView和RecyclerView对比

通过上面两张图我们可以看出,ListView和RecyclerView的缓存设计都包含了create和bind的过程,当缓存没有命中时通过create构建新的对象,当缓存命中时通过bind来复用对象。
在设计上,RecyclerView由于将布局(LayoutManager)、分割线(ItemDecoration)和动画(ItemAnimator)分离出来使得其对列表视图的控制要比ListView更加灵活。

在效率上,RecyclerView相比ListView要更加高效体现在其对缓存的控制上更加精细,主要体现在以下两点:

  • 减少bind方法的调用频次。当视图滚动,缓存命中的情况下,ListView会将缓存中UI绑定的数据清空并重新初始化,而RecyclerView将缓存细分为两种,一种是mAttachedScrap,另一种是RecyclerViewPool。首先匹配mAttachedScrap,当mAttachedScrap中存在时直接使用其UI以及UI绑定的数据,不用重新初始化。这种通过增加少量内存开销从而减少bind方法的调用的方式,可以进一步提高视图的加载和显示效率。此外,RecyclerView还提供了局部刷新的方式来进一步减少了bind方法的调用频次,从而进一步优化了性能。
  • 多个RecyclerView之间的缓存共享,RecyclerView的RecyclerViewPool可以由开发者自己指定,灵活控制缓存的容量大小,这在某些场景下,比如使用viewpager来实现多个类似列表页面的展示,是非常有用的,我们可以将多个页面的RecyclerViewPool进行复用从而进一步降低缓存的内存开销。

在使用上,四级缓存以及控制上的灵活设计,导致RecyclerView的实现比ListView复杂了许多,使用门槛上也更高了一些。所以,当我们在实现列表视图时需要根据实际的业务场景来进行选择。如果是一些比较简单的类型单一的静态列表页,使用ListView会更方便,代码量更少,当然如果你对RecyclerView封装的比较好,也可以做到使用很少的代码就能满足需求。如果是类型复杂或者需要频繁动态更新的列表页,还是推荐RecyclerView来实现。

总结

不论是ListView还是RecyclerView,他们的缓存设计思想都值得我们借鉴和学习。从预加载到懒加载,从全局刷新到局部刷新,这种时间换空间和空间换时间的优化思路不仅可以用在列表视图中,也可以用在其他的场景中。盘点一下我们在应用开发中的各种业务场景,朝着这个方向,相信你总能找出优化的点来。

参考文档

Android ListView 与 RecyclerView 对比浅析--缓存机制

可视化 ListView 缓存机制,手摸手带你打通任督二脉

手摸手第二弹,可视化 RecyclerView 缓存机制

RecyclerView剖析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容