再次探究Android ListView缓存机制
概述
虽然现在5.0后Google推出了RecycleView,但在5.0 Lollipop普及前Listview仍会被广泛使用,所以打算再次探究一下Listview的源码,了解一下Listview 的构成及加载机制。
探究

上图简单梳理了Listview的构成及与其相关类之间的关系,并简要地列出了些重要的方法和内部类。
AdapterView
从上图可以清晰的看出Listview归根究底是继承自AdapterView。AdaterView是一个抽象类,一些最基本和通用方法或接口都是在此定义或声明的,其中一些更是开发者所常用的,诸如:
//Item Click 监听接口
/**
* Interface definition for a callback to be invoked when an item in this
* AdapterView has been clicked.
*/
public interface OnItemClickListener {
... ...
void onItemClick(AdapterView<?> parent, View view, int position, long id);
}
//设置Adapter抽象方法
/**
* Sets the adapter that provides the data and the views to represent the data
* in this widget.
*
* @param adapter The adapter to use to create this view's content.
*/
public abstract void setAdapter(T adapter);
此外在AdapterView中实现了DataSetObserver抽象类,我们一般调用mAdapter.notifyChanged()所触发的就是DataSetObserver的onChanged()方法。关键源码如下:
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
... ...
}
@Override
public void onInvalidated() {
mDataChanged = true;
... ...
}
... ...
}
AbsListView
AbsListView是继承自AdapterView,在该类中实现了一个非常重要的内部类RecycleBin,内部类RecycleBin其实就是AbsListView缓存机制的核心类,它的作用是管理AbsListView的item存储和取得。AbsListview的缓存分为两级,第一级为activeView,第二级为scrapview。二者的间的转换主要是在layoutChildren()方法进行(该抽象方法在LisView中实现),具体分析见如下源码:
@Override
protected void layoutChildren() {
... ...
//说明RecycleBin并不缓存HeadView和FooterView
// Don't put header or footer views into the Recycler.
//Those are already cached in mHeaderViews;
if (dataChanged) {
//如果data改变了,则当前所有childView都添加至mScrapViews;
for (int i = 0; i < childCount; i++) {
recycleBin.addScrapView(getChildAt(i), firstPosition+i);
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(getChildAt(i),
ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, index, i);
}
}
} else {
//若data未改变,即第一次加载时,根据当前childCount数量对mArchiveViews赋值。
recycleBin.fillActiveViews(childCount, firstPosition);
}
... ...
switch (mLayoutMode) {
... ...(在switch条件中执行makeAndAddView函数)
}
// Flush any cached views that did not get reused above
//执行makeAndAddView函数后将需要显示的item view已添加至ListView中,
//所以跳出siwtch后会将缓存的mActiveViews全部转换为mScrapViews。
recycleBin.scrapActiveViews();
... ...
}
同时AbsListview中定义了一个ObtainView方法,一般地当Listview加载时若发现没有可复用的itemView时要么从RecycleBin中转换ScrapView,要么是通过mAdapter.getView()获取新的itemView,ObtainView方法就是专门用来处理上述的两种情况,具体分析如下:
View obtainView(int position, boolean[] isScrap) {
... ...
scrapView = mRecycler.getScrapView(position);
View child;
//若scrapView不为空,则将scrapView转换为可复用的itemView
if (scrapView != null) {
... ...
child = mAdapter.getView(position, scrapView, this);
... ...
}else{
//若scrapView为空,则通过adapter.getView()函数获取新的ItemView
child = mAdapter.getView(position, null, this);
... ...
}
}
结语
OK,今天就先总结这么多了,不足之处欢迎指出。当然今后使用RecycleView会是一种趋势,和AS一样,找机会要研究一下。
作者:XycZero
查看原文:http://www.xyczero.com/blog/article/18/.
再次探究Android ListView缓存机制的更多相关文章
- ListView缓存机制踩过的坑
ListView,GrildView使用时候经常会用到缓存机制,随意一搜,例子成千上万,但是讲解都是很一致,跟自己踩的坑很少有人讲解到. 测试 需求: GrildView 分三列显示,默认背景为白色, ...
- 解决ListView 缓存机制带来的显示不正常问题
ListView加载数据原理:系统绘制ListView时,首先会用getCount()函数得到要绘制的这个列表的长度,然后开始逐行绘制.然后调用getView()函数,在这个函数里面首先获得一个Vie ...
- android 双缓存机制
废话不多说,直接贴代码! 所谓的双缓存,第一就是缓存在内存里面,第二就是缓存在SD卡里面,当你需要加载数据时,先去内存缓存中查找,如果没有再去SD卡中查找,并且用户可以自选使用哪种缓存! 缓存内存和缓 ...
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
在本系列的上一篇文章中,我带着大家一起阅读了一遍Glide的源码,初步了解了这个强大的图片加载框架的基本执行流程. 不过,上一篇文章只能说是比较粗略地阅读了Glide整个执行流程方面的源码,搞明白了G ...
- Android性能优化之ListView缓存机制
要想优化ListView首先要了解它的工作原理,列表的显示须要三个元素:ListView.Adapter.显示的数据. 这里的Adapter就是用到了适配器模式,无论传入的是什么View在ListVi ...
- Android WebView 缓存机制和模式详解
当我们加载Html时候,会在我们data/应用package下生成database与cache两个文件夹: 我们请求的Url记录是保存在webviewCache.db里,而url的内容是保存在webv ...
- Android笔记(二十五) ListView的缓存机制与BaseAdapter
之前接触了ListView和Adapter,Adapter将数据源和View连接起来,实际应用中,我们要显示的数据往往有很多,而屏幕只有那么大,系统只能屏幕所能显示的内容,当我们滑动屏幕,会将旧的内容 ...
- RecyclerView 源码分析(二) —— 缓存机制
在前一篇文章 RecyclerView 源码分析(一) -- 绘制流程解析 介绍了 RecyclerView 的绘制流程,RecyclerView 通过将绘制流程从 View 中抽取出来,放到 Lay ...
- H5 和移动端 WebView 缓存机制解析与实战
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/qHm_dJBhVbv0pJs8Crp77w 作者:叶 ...
随机推荐
- 关于数据库一致改关闭下redo日志文件丢失的处理办法的总结
数据库一致性关闭下redo日志文件丢失的处理办法(归档和非归档都行) 1. inactive log 在一致性关闭后删除重启时可以在mount下(不丢失数据) alter database clea ...
- postgresql数据库的数据导出
一.pg_dump的用法:数据库的导入导出是最常用的功能之一,每种数据库都提供有这方面的工具,例如Oracle的exp/imp,Informix的dbexp/dbimp,MySQL的mysqldump ...
- winform 导出TXT 分类: WinForm 2014-05-15 15:29 128人阅读 评论(0) 收藏
截图: 代码实现:(导出txt按钮事件) using System.IO; using System.Data.OleDb; private void btnOutTxt_Click(object s ...
- Android RecyclerView使用(一)
RecyclerView一种可以替换掉listview gridview 瀑布流等控件的新视图控件,控制视图回收和复用 ==优化内存可以替换listview 与listview的不同之处是:listv ...
- 【LeetCode】Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- Cubieboard 开箱和入门 | Name5566 分类: cubieboard 2014-11-08 17:27 251人阅读 评论(0) 收藏
Cubieboard 开箱和入门 2014 年 01 月 29 日 by name5566 Categories: Computer Science, Cubieboard Hello Cubiebo ...
- [Flux] 2. Overview and Dispatchers
Flux has four major components: Stores, Dispatchers, Views, and Actions. These components interact l ...
- [Javascript] Array - Conact
For example there are two array of object and you want to print out each element, it is bad if you u ...
- 在Linux下用netstat查看网络状态、端口状态
在Linux下用netstat查看网络状态.端口状态 在linux一般使用netstat 来查看系统端口使用情况步. netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表.实 ...
- (转)高性能I/O模型
本文转自:http://www.cnblogs.com/fanzhidongyzby/p/4098546.html 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO ...