探究ListView 的缓存机制
概述
ListView 是继承AbListView,AbListView是所有列表类控件的基类。
ListView的数据加载
在ListView数据加载中最关键的一个函数就是makeAndAddView(),这个函数的作用就获得一个ChildView并把该ChildView添加到List中,具体见源码分析:
private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
boolean selected) {
View child;//即ChildView
//如果数据没有发生改变
if (!mDataChanged) {
//优先从循环器中获取该位置的视图
// Try to use an existing view for this position
child = mRecycler.getActiveView(position);
if (child != null) {
// Found it -- we're using an existing child
//如果找到了就直接添加到List中
// This just needs to be positioned
setupChild(child, position, y, flow, childrenLeft, selected, true);
return child;
}
}
//如果数据发生了改变,则在该位置上新建一个视图,或者如果可能的话转换一个已经没有用的视图(可能是当整个ListView其他位置发生了变化,但是该位置的ChildView并未发生任何变化)
// Make a new view for this position, or convert an unused view if possible
child = obtainView(position, mIsScrap);
// This needs to be positioned and measured
setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);
//返回该childView
return child;
}
ListView的缓存机制
当ListView发生滑动操作时,若干已经加载的ChildView会被因滑动而被暂时隐藏掉,为了避免下次显示再重新加载,这时ListView的缓存机制就会被触发,即运行layoutChildren()函数(其实任何触碰事件都会触发,即onTouchEvent() -。-)。
那么ListView的缓存机制是依靠什么来缓存的呢?答案就是AbListView中 的内部类RecycleBin。关于RecycleBin的具体作用,源码中的注释已经解释的非常清楚了,在此就不在赘述。
/**
* The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
* storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
* start of a layout. By construction, they are displaying current information. At the end of
* layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
* could potentially be used by the adapter to avoid allocating views unnecessarily.
*... ...
*/
当需要缓存ActiveViews时会调用fillActiveViews()函数,该函数会把ListView中的所有ActiveViews 一次性都缓存起来。
/**
* Fill ActiveViews with all of the children of the AbsListView.
* ... ...
*/
void fillActiveViews(int childCount, int firstActivePosition) {
if (mActiveViews.length < childCount) {
mActiveViews = new View[childCount];
}
mFirstActivePosition = firstActivePosition;
//noinspection MismatchedReadAndWriteOfArray
final View[] activeViews = mActiveViews;
... ...
}
而对于ScrapViews则是调用的addScrapView()函数。
/**
* Puts a view into the list of scrap views.
* <p>
* If the list data hasn't changed or the adapter has stable IDs, views
* with transient state will be preserved for later retrieval.
*
* @param scrap The view to add
* @param position The view's position within its parent
*/
void addScrapView(View scrap, int position) {
... ...
// Don't scrap views that have transient state.
final boolean scrapHasTransientState = scrap.hasTransientState();
if (scrapHasTransientState) {
//Transient状态
... ...
}else{
//scrap状态
... ...
}
... ...
}
该函数中又分为两个不同的level,一个是transient瞬时态,另一个就是一般的普通态,关于这两个状态的区分我个人的想法是为了更加快速的获取ScrapViews,因为处于瞬时状态的view最有可能是接下来将要在界面上显示的View,毕竟你向上或向下滑动列表时目的就是这个,这一点在obtainView()函数中得到了体现:
View obtainView(int position, boolean[] isScrap) {
... ...
//优先获取TransientStateView
scrapView = mRecycler.getTransientStateView(position);
if (scrapView == null) {
scrapView = mRecycler.getScrapView(position);
}
... ...
}
还有一个比较重要的函数就是scrapActiveViews()函数,它的作用是将目前所有的ActiveViews降级为ScrapViews,并将之前的所有ScrapViews清除。该函数在每次调用layoutChildern()函数时必定会被调用执行,目的就是为清空所有当前的ActiveViews,为新产生的ActiveViews做好准备。
/**
* Move all views remaining in mActiveViews to mScrapViews.
*/
void scrapActiveViews() {
... ...
//该函数确保mScrapViews的大小不会超过mActiveViews
pruneScrapViews();
}
结语
以上是阅读了ListView以及AbListView源码后的一些心得总结,毕竟阅读Android源码也才刚刚起步,还有很多地方理解的不是很透彻,上文若有理解不当之处欢迎各位指正。
探究ListView 的缓存机制的更多相关文章
- Android学习——ListView的缓存机制
在使用ListView的时候,需要加载适配器和数据源,这篇文章主要介绍一下ListView的使用以及利用ListView的缓存机制来减少系统的初始化时间. ListView的使用 ListView和V ...
- Android笔记(二十五) ListView的缓存机制与BaseAdapter
之前接触了ListView和Adapter,Adapter将数据源和View连接起来,实际应用中,我们要显示的数据往往有很多,而屏幕只有那么大,系统只能屏幕所能显示的内容,当我们滑动屏幕,会将旧的内容 ...
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
在本系列的上一篇文章中,我带着大家一起阅读了一遍Glide的源码,初步了解了这个强大的图片加载框架的基本执行流程. 不过,上一篇文章只能说是比较粗略地阅读了Glide整个执行流程方面的源码,搞明白了G ...
- 【腾讯Bugly干货分享】Android ListView与RecyclerView对比浅析--缓存机制
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d3e3ab10c62013697408 作者:黄宁源 一,背景 Recy ...
- RecyclerView与ListView 对比浅析:缓存机制
一. 背景 PS:相关知识:ListView与RecyclerView缓存机制原理大致相似,如下图所示: 滑动过程中,离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取, ...
- ListView与RecyclerView对比浅析——缓存机制
https://www.jianshu.com/p/193fb966e954 一,背景 RecyclerView是谷歌官方出的一个用于大量数据展示的新控件,可以用来代替传统的ListView,更加强大 ...
- RecyclerView 源码分析(二) —— 缓存机制
在前一篇文章 RecyclerView 源码分析(一) -- 绘制流程解析 介绍了 RecyclerView 的绘制流程,RecyclerView 通过将绘制流程从 View 中抽取出来,放到 Lay ...
- 再次探究Android ListView缓存机制
概述 虽然现在5.0后Google推出了RecycleView,但在5.0 Lollipop普及前Listview仍会被广泛使用,所以打算再次探究一下Listview的源码,了解一下Listview ...
- [转]Android ListView 与 RecyclerView 对比浅析—缓存机制
从源码角度剖析ListView 与 RecyclerView 缓存机制的不同 https://zhuanlan.zhihu.com/p/23339185 原文地址:http://dev.qq.com/ ...
随机推荐
- HDOJ 1715 大菲波数
Problem Description Fibonacci数列,定义如下: f(1)=f(2)=1 f(n)=f(n-1)+f(n-2) n>=3. 计算第n项Fibonacci数值. Inpu ...
- ARM机器码分析
我们编写的汇编程序还是不够底层,CPU都是对机器码进行操作的,所以还需要用汇编器将汇编代码转换成机器码才能被CPU处理.下面举几个例子来说说分析ARM机器码的方法. 对编译连接之后得到的ELF进行反汇 ...
- win10在安装Oracle11g时出现了:[INS-13001]环境不满足最低要求,及未找到文件 E:\app\xxj\product\11.2.0\dbhome_1\owb\external\oc4j_applications\applications\WFMLRSVCApp.ear
win10安装Oracle11g碰到的3个问题: 1.win10在安装Oracle11g时出现了:[INS-13001]环境不满足最低要求 2.未找到文件 E:\app\xxj\product\11. ...
- GitHub 的分支创建与合并
一个Git仓库可以维护很多开发分支.现在我们来创建一个新的叫"experimental"的分支: $ git branch experimental 如果你运行下面这条命令: $ ...
- bzoj3669: [Noi2014]魔法森林 lct
记得去年模拟赛的时候好像YY出二分答案枚举a,b的暴力,过了55欸 然后看正解,为了将两维变成一维,将a排序,模拟Kruskal的加边过程,同时维护1到n的最大值,加入一条边e(u,v,a,b)时有以 ...
- 去除TFS版本控制信息
为了避免对版本库的影响,可以自己离线的修改代码,就要脱离TFS的管理,解决方案: 1.找到*.sln文件用文本打开,可以找到: Global GlobalSection(SolutionConfigu ...
- java——递归调用
递归函数调用调用本身,并通过自己的相应参数,这个计算过程中进行层,直到满足某些条件,只要停止呼叫. 递归函数的特点 1.函数要直接或间接调用自身. 2.要有递归终止条件检查.即递归终止的条件被满足后. ...
- 深入分析 Java 中的中文编码问题--转
几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...
- Oracle 存储过程(2)
http://www.cnblogs.com/chinafine/archive/2010/07/12/1776102.html http://blog.itpub.net/29485627/view ...
- jQuery的矿建结构小demo举例
(function (global) { var document = global.document,//变成局部变量提高搜索的性能 init;// 核心函数 function itcast(sel ...