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

项目地址:ListViewVisualizationgit

简介

本文不涉及 ListView 缓存机制的源码探析,关于 ListView 的缓存机制郭霖前辈的《Android ListView工做原理彻底解析,带你从源码的角度完全理解》已经分析的很通彻了,同理网上也有不少文章了。本文不针对 ListView 的缓存机制作介绍,对于这块还不够了解的朋友能够阅读上方郭霖前辈的文章。另外再配上腾讯 Bugly 的图:github

这里写图片描述

痛点

对于像 ListView/RecyclerView 这种级别 View 的源码是长篇且晦涩的,连郭霖前辈本身也说过 “没过几个月时间我就把当初梳理清晰的源码又忘的一干二净”。且网上的文章都是针对代码阐述的,实在是有些难以理解,且部分知识点并未涉及(例如仅针对 ViewType 只有一种状况的情形作说明,多 ViewType 情形下缓存机制少见阐述)。笔者遇到这些问题时候仍是很头疼的,因而就将 ListView 的缓存机制给可视化,再针对各个情形加以总结,相信能帮助到不少对 ListView 缓存机制不太熟悉的读者们。数组

缓存机制解析

项目地址:ListViewVisualization或者你能够直接安装:apk。 在手摸手解析以前,须要说起到 RecycleBin 中的几个字段 ,这些字段在郭霖前辈的文章中基本都有所说起,实际上掌握了这些字段在 ListView 缓存机制中变换的状况,笔者认为对 ListView 的缓存机制了解就算是比较通彻的了——缓存

  • mCurrentScrap:ArrayList 类型,用于存储离屏的 View
  • mScrapViews
    • ArrayList[] 类型
    • 数组中每一个元素都是 ArrayList 类型,效果同 mCurrentScrap
    • mScrapViews[0] 就是 mCurrentScrap
    • 其数组长度应为 ViewTypeCount。由于针对不一样的 ViewType,ListView 都要有一个专门的 ArrayList 链表来缓存它对应的 View
  • mActiveView:ArrayList 类型,被 layoutChildren() 用于缓存屏幕上的 View。

文章中说起的部分名词:项目中 ListView 使用了两个 ViewType,也就是有两种布局,其中第一种笔者在文中说起到时命名为 Item1,第二种称为 Item2markdown

初始化

这里写图片描述

mActiveViews:长度为4。在笔者的手机上初始化时屏幕上只能容下4个 View mScrapViews:长度为2。笔者设置了两种 ViewType,因此须要有两套缓存 View 的 ArrayList mCurrentScrap/mScrapViews[0]:长度为0。此时缓存区确定是0,由于没有滑动因此不存在缓存 View 一说。 mScrapViews[1]:长度为0。这个就更不解释啦。app

触发第一个缓存

这里写图片描述

当 『1』 被移出屏幕的时候,mCurrentScrap/mScrapViews[0] 就要动手将它缓存起来啦,做为下一个进入屏幕的 View 的复用。在图上此时也多出了一句 the last one of mCurrentScrap's type is ItemX---number,为何要关注 mCurrentScrap 的最后一个值?由于 RecycleBin 在滑动区域都是 Item1 的状况下,取出缓存的方式就是从末尾获取一个 View,因此咱们须要关注一下末尾 View 的类型,可是实际上在整个过程当中该值的意义也并不大,纯粹是为了展现离屏 Item 信息。至于 ItemX 后面的数字,则是废弃 View 中 TextView 中所显示的 text 了。因此第一个缓存是一个 Item1 类型的 TextView 显示为 1 的 View 被移出屏幕了。oop

同理:当『2』被滑出屏幕的时候,『2』这个 View 将会被缓存起来,此时屏幕上应该显示了 the last one of mCurrentScrap's type is Item1---2,各位读者能够试试。布局

屏幕内容数量最大化

屏幕继续下滑啊下滑~

这里写图片描述

屏幕下滑没多少就会忽然发现 mCurrentScrap/mScrapView[0] 为 0 啦,这说明此时 RecycleBin 中没有缓存!由于此时屏幕中已经显示了 『2』~『6』共 5 个 View 了,以前的 『1』 已经被 『6』 复用了,因此不存在还有缓存了。实际上针对于 ViewType 只有一种的状况来讲,RecycleBin 机制中的 mCurrentScrap/mScrapViews[0] 的大小永远是1。由于它至多只须要缓存一个 View,由于屏幕内容数量的最大值一定为初始时屏幕内容数量值 + 1,拿笔者的手机举例来讲,初始值为4,屏幕内容数量的最大值则为 5。spa

触发 Item2 的显示

笔者将 Item1 的数量设置为 17,当咱们挪到 17 继续下滑时将会发生什么情形?

这里写图片描述

一切都在掌控以内。.net

继续触发

屏幕继续下滑,直至『14』被移出屏幕——

这里写图片描述

当『14』被移出后,mCurrentScrap/mScrapViews[0] 的 size 从百年不变的 1 变成了 2。为何?由于『13』 用不上了,新出来的 View 是 Item2 而不是 Item1,因此缓存只能无奈的加加加,而不能被复用。咱们不妨移动到全屏为 Item2 ——

这里写图片描述

直至『17』移出屏幕,mCurrentScrap/mScrapViews[0] 的大小最终达到了 5。

总结

什么玩意儿,刚进 Item2 区域就总结啦?就总结啦!由于纯粹的 Item2 区域滑动和纯粹的 Item1 区域滑动状况是同样的;而 Item2 区域滑向 Item1 区域的情形与 Item1 区域滑向 Item2 区域的情形也是同样的。因此本文授人以渔的任务就完成了,剩下的就是各位读者实操捕鱼的过程了。
相关文章
相关标签/搜索