概述

虽然现在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缓存机制的更多相关文章

  1. ListView缓存机制踩过的坑

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

  2. 解决ListView 缓存机制带来的显示不正常问题

    ListView加载数据原理:系统绘制ListView时,首先会用getCount()函数得到要绘制的这个列表的长度,然后开始逐行绘制.然后调用getView()函数,在这个函数里面首先获得一个Vie ...

  3. android 双缓存机制

    废话不多说,直接贴代码! 所谓的双缓存,第一就是缓存在内存里面,第二就是缓存在SD卡里面,当你需要加载数据时,先去内存缓存中查找,如果没有再去SD卡中查找,并且用户可以自选使用哪种缓存! 缓存内存和缓 ...

  4. Android图片加载框架最全解析(三),深入探究Glide的缓存机制

    在本系列的上一篇文章中,我带着大家一起阅读了一遍Glide的源码,初步了解了这个强大的图片加载框架的基本执行流程. 不过,上一篇文章只能说是比较粗略地阅读了Glide整个执行流程方面的源码,搞明白了G ...

  5. Android性能优化之ListView缓存机制

    要想优化ListView首先要了解它的工作原理,列表的显示须要三个元素:ListView.Adapter.显示的数据. 这里的Adapter就是用到了适配器模式,无论传入的是什么View在ListVi ...

  6. Android WebView 缓存机制和模式详解

    当我们加载Html时候,会在我们data/应用package下生成database与cache两个文件夹: 我们请求的Url记录是保存在webviewCache.db里,而url的内容是保存在webv ...

  7. Android笔记(二十五) ListView的缓存机制与BaseAdapter

    之前接触了ListView和Adapter,Adapter将数据源和View连接起来,实际应用中,我们要显示的数据往往有很多,而屏幕只有那么大,系统只能屏幕所能显示的内容,当我们滑动屏幕,会将旧的内容 ...

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

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

  9. H5 和移动端 WebView 缓存机制解析与实战

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/qHm_dJBhVbv0pJs8Crp77w 作者:叶 ...

随机推荐

  1. centos下apache thrift的安装

    参考:http://running.iteye.com/blog/1983463  thrift-0.9.0安装 最好切换到root用户操作,避免不必要的麻烦. 进行例子程序tutorial目录下,通 ...

  2. Pencil-一个开源免费的UI原型工具,自带ios和android模板

    Pencil是一个开源免费的UI原型工具,自带ios和android模板,可以很方便的做mockup. 下图是一个官方展示的模板:         

  3. Python爬取CSDN博客文章

    0 url :http://blog.csdn.net/youyou1543724847/article/details/52818339Redis一点基础的东西目录 1.基础底层数据结构 2.win ...

  4. Memo打印1

              Delphi 打印Memo里面的内容 实现的功能和记事本的打印的功能一样 打印保存为文件时此时的文件名如何设置? 当Memo里的文本数量巨大时 窗体正在打印会出现点数字显示问题 闪 ...

  5. Node.js异步处理CPU密集型任务

    Node.js异步处理CPU密集型任务 Node.js擅长数据密集型实时(data-intensive real-time)交互的应用场景.然而数据密集型实时应用程序并非仅仅有I/O密集型任务,当碰到 ...

  6. git学习 #2:git基本操作

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

  7. Marquee滚动字幕设置(转)

    <marquee >滚动文字 </marquee> 方向 <direction=#> #=left, right,up,down 方式<bihavior=#& ...

  8. apache不解析php文档?提示需要下载(转)

    在httpd.cong中 LoadModule php5_module modules/libphp5.so #这一行php5安装的时候就已经自动添加上了 AddType application/x- ...

  9. android 15 activity跳转

    从一个屏幕跳到另一个屏幕,一个activity跳转到另一个activity,Intent类用于组件之间传递数据和跳转,组件包括不仅activity. package com.sxt.day04_01; ...

  10. Java NIO类库Selector机制解析--转

    一.  前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但引入了全新的高效的I/O机制,同时,也引入了多路复用的异步模式.NIO的包中主要包含了这样几种抽象数据类型: ...