Android之了解 ListView缓存机制

1.什么是ListView

在android开发中ListView是非常常用的组件,它以列表的形式来表示,即使是数据够大,也能根据数据的长度进行自适应来显示。在一定条件下,其加载大量的数据也不会发生OOM。

在android开发文档可以看到ListView是直接继承于AbsListView,AbsListView又继承AdapterView,AdapterView继承ViewGroup:


用过listview的开发者都知道adapter,至于为什么要出现adapter呢,试想一下:如果没有adapter,让listview和数据源直接接触,那么listview就要做大量的适配工作,因为数据源的类型有太多,有可能是一个数组,也有可能是一个集合等等。如果listview去和每一种数据源进行适配的话会导致代码极其臃肿并且违背了它所显示的原则。这时候很有必要需要一个东西去做适配工作,android就出现了adapter这个机制,原理如下图:


adapter中除了要适配数据源的工作以外还要写一些逻辑是在getView()。

2.ListView工作原理

ListView的工作原理是:例如当屏幕需要显示9个item时,那么ListView只会创建10个视图,当第一个item离开屏幕时,那么第一个item就会拿来复用,用来显示第10个item,这种设计是非常棒的。最重要的一个原因是RecycleBin机制,RecycleBin是作为内部类在AbsListView里面,因此ListView会用到其机制。那么现在仔细分析RecycleBin:

(1)成员变量:

 

(2)setViewTypeCount(int viewTypeCount)是初始化


(3)fillActiveViews(int childCount,int firstActivePosition)来存放可见的view,根据参数意思:childCount存放View的数量,firstActivePosition是第一个可见的位置


(4)addScrapView(View scrap,int position)来存放不在于屏幕内的View



(5)getScrapView(int position)从缓存的View获取


(6)getActiveView(int position)这个方法是得到屏幕上某个位置的显示的view


(7)getTransientStateView(int position) 获取具有TransientState状态的View,获取后会移除


(8)retrieveFromScrap(ArrayList<View> scrapViews,int position)根据参数可知 是从缓存数组获取对应的view


(9)clearTransientStateViews() 清除具有TransientStateViews的View


(10)pruneScrapViews()当缓存的数组大于屏幕上活跃的数组后就会走这个方法,在scrapActiveViews()这个方法内调用,至于为什么要清理呢?主要是因为TransientStateView数组中的View的transient属性消失后,会缓存两次,一遍是具有transientState的view,另一遍是View不具有transientState又会缓存一遍,这样缓存中就会导致活跃中的数组,因此需要处理。


(11)markChildrenDirty()可以看到里面调用缓存的view的forceLayout,这个方法只会执行自己的onMeasure()和onLayout()方法,当ListView的size改变时进行调用。


3.ListView的绘制

因为ListView 和 GridView都是继承View的,那缓存的逻辑应该写在AbsListView里面,那里面肯定有onMeasure()方法和onLayout()方法,去看看:



可以看见onLayout()方法其实就是当ListVIew发生变化后,要求子布局进行重绘。

在看ListView中的layoutChildren();这个方法源码就不贴了,这个方法主要是确定布局模式,并且确定布局顺序,从顶到底去填充ListView,里面有fillFromTop(int nextTop)这个方法里面调用fillDown(int pos,int nextTop)这个方法主要是遍历当前显示在屏幕上的view,并且缓存起来通过执行makeAndAddView()方法,里面在调用setupChild()方法,最后实际上调用obtainView()方法去获取一个view,里面实际上调用了我们最熟悉的getView(),参数有三个分别是位置,convertView,还有this,也就是说当填满整个屏幕后,就不在绘制了。另外第二次Layout郭霖博客已经描述很清晰了,这里不再叙述。具体是:先调用detachAllViewsFromParent()方法清掉所有的view,然后再用缓存的view去添加进行加载,最后不会执行obtainView(),因为如果又要infalte,使效率大大降低,最后重新attachViewToParent()方法。

简单的流程图如下:





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值