ListView源代码分析

继承关系

1、UML图

图中单独画出Scrollview是为了说明该ViewGroup并没有自带回收机制,如果要是Scrollview显示大量view,需要手动做处理。

2、继承体系的分工

(1) AdapterView

An AdapterView is a view whose children aredetermined by an {@link Adapter}.

a.adapter相关的抽象函数:getAdapter、setAdapter

b.mEmptyView

c.观察者模式

d. Accessibility:Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音,触觉反馈,手势操作,轨迹球和手柄操作。

(2)AbsListView

Base class that can be used to implementvirtualized lists of items. A list does not have a spatial definition here. Forinstance, subclases of this class can display
the content of the list in agrid, in a carousel, as stack, etc.

1.拥有RecycleBin类,负责处理view的生成和回收,没有子视图的空间定位信息

2.滑动事件相关(touch orfling-based scrolling)

(3)ListView

A view that shows items in a verticallyscrolling list. The items come from the {@link ListAdapter} associated withthis view.

以垂直列表显示数据,具体控制列表项的排布和位移

Header和footer相关

3.优点:层次清晰,易于扩展

RecycleBin类(实现回收机制)

1.成员变量

(1)mFirstActivePosition

The position of the first view stored inmActiveViews.

存储在mActiveViews中的第一个view的位置,即一个可视的子视图

(2)mActiveViews

View[]

Views that were on screen at the start oflayout. This array is populated at the start of layout, and at the end oflayout all view in mActiveViews are moved to
mScrapViews. Views in mActiveViewsrepresent a contiguous range of Views, with position of the first view store in

mFirstActivePosition.

布局开始时屏幕显示的view,这个数组会在布局开始时填充,布局结束后所有view被移至mScrapViews。

(3)mScrapViews

ArrayList<View>[]

Unsorted views that can be used by theadapter as a convert view.

可以被适配器用作convert view的无序view数组。这个ArrayList就是adapter中getView方法中的参数convertView的来源。注意:这里是一个数组,因为如果adapter中数据有多种类型,那么就会有多个ScrapViews。

2.成员函数

(1)shouldRecycleViewType

判断给定的view的viewType指明是否可以回收回。

viewType < 0可以回收。指定忽略的(ITEM_VIEW_TYPE_IGNORE
= -1),或者是 HeaderView / FootView(ITEM_VIEW_TYPE_HEADER_OR_FOOTER
= -2)是不被回收的。如有特殊需要可以将自己定义的viewType设置为-1,否则,将会浪费内存,导致OOM。

(2) retrieveFromScrap

a.第三种情况,这个最简单:

一开始,listview稳定后,此时mScrapView中是没有缓存view的,当我们向上滚动一小段距离(第一个此时仍显示部分),新的view将会显示,此时listview会调用Adapter.getView,但是缓存中没有,因此convertView是null,所以,我们得分配一块内存来创建新的convertView;

b.第二种情况:

在a中,我们继续向上滚动,直接第一个view完全移出屏幕(假设没有新的item),此时,第一个view就会被detach,并被加入到mScrapView中;然后,我们还继续向上滚动,直接后面又将要显示新的item
view时,此时,系统会从mScrapView中找position对应的View,显然,是找不到的,则将从mScrapView中,取最后一个缓存的view传递给convertView;

c.第一种情况:

AbsListView中的LayoutParams继承了ViewGroup的LayoutParams,其中一个增加的成员变量是scrappedFromPosition,这个变量是由addScrapView时传递进来的position赋值,就是当时要回收的view的位置。所以scrappedFromPosition==
position的判断就是,如果某个位置的view被回收了,此时该位置又要重新显示出来,那么优先显示原来的view,就是尽量保持原来位置的view不变。当然,如果原来的view已经用在别的位置了,那就没办法了。

(3) pruneScrapViews

确保mScrapViews的数目不会超过mActiveViews的数目
(This can happen if an adapter does not recycle its views)。mScrapView中每个ScrapView数组大小不应该超过mActiveView的大小,如果超过,系统认为程序并没有复用convertView,而是每次都是创建一个新的view,为了避免产生大量的闲置内存且增加OOM的风险,系统会在每次回收后,去检查一下,将超过的部分释放掉,节约内存降低OOM风险。

生成新子视图,即调用mAdapter.getView

1.private void scrollListItemsBy(int amount)

调用情景:按列表项逐项移动,由onKeyDown、onKeyUp、onKeyMultiple调用

commonKey-->arrowScrollImpl-->arrowScrollImpl-->scrollListItemsBy

(1)初始化:

其中offsetChildrenTopAndBottom是将所有子视图移动指定的像素:

最终调用mDisplayList的offsetTopBottom

(2)向上滑动的分支:

(3)

  

2.列表滑动生成列表项视图

(1)滑动时的调用堆栈

onTouchEvent (AbsListView)àscrollIfNeeded
(AbsListView)

或者FlingRunnable (AbsListView)

à

trackMotionScroll (AbsListView)

à

fillGap

(在AbsListView中为抽象函数,在ListView中实现;向下调用fillDown,向上调用fillUp)

(在调用fillGap之前会调用offsetChildrenTopAndBottom)

à

makeAndAddView (ListView)

没有数据变化:从mRecycler中取得可视的view

数据有变化:obtainView-->setupChild

(2)重点分析:

1)obtainView:生成view,回收旧view和调用mApapter.getView的地方(AbsListView)

2)第一行的getScrapView最后调用第二部分分析RecycleBin类的retrieveFromScrap

3)setupChild:将view添加到viewgroup,对子视图定位(ListView)

关键步骤:

a. attachViewToParent或者addViewInLayout

b. child.measure(childWidthSpec,childHeightSpec);

c. child.layout(childrenLeft, childTop,childRight, childBottom);

3.
再谈回收

如果实现了RecyclerListener接口,当一个View由于ListView的滑动被系统回收到RecycleBin的mScrapViews数组时,会调用RecyclerListener中的onMovedToScrapHeap(View
view)方法。RecycleBin相当于一个临时存储不需要显示的那部分Views的对象,随着列表滑动,这些Views需要显示出来的时候,他们就被从RecycleBin中拿了出来,RecycleBin本身并不对mScrapViews中的对象做回收操作。

于是在工程里,为ListView添加RecyclerListener接口,并在onMovedToScrapHeap方法中释放ListItem包含的Bitmap资源,这样可以极大的减少内存占用。

关于RecyclerListener接口的注释:

Sets the recycler listener to be notifiedwhenever a View is set aside in the recycler for later reuse. This listener canbe used to free resources associated to
the View.

时间: 2024-10-13 13:13:13

ListView源代码分析的相关文章

Android万能适配器base-adapter-helper的源代码分析

项目地址:https://github.com/JoanZapata/base-adapter-helper 1. 功能介绍 1.1. base-adapter-helper base-adapter-helper 是对传统的 BaseAdapter ViewHolder 模式的一个封装.主要功能就是简化我们书写 AbsListView 的 Adapter 的代码,如 ListView,GridView. 1.2 基本使用 mListView.setAdapter(mAdapter = new

ViewFlow增强onItemClick功能及ViewFlow AbsListView源代码分析

先看实现效果,上图: ViewFlow是一个非常好用的,用于不确定item个数的水平滑动切换的开源项目. 可是从github上下载的ViewFlow事实上是不支持onItemClick功能的,touch事件中并没有处理click. 那么怎样去支持onItemClick功能呢? 一.在实现前,先带着三个问题: 序号 问题 1 ViewFlow须要OnItemClickListener接口吗? 2 ListView又是怎样实现OnItemClick的呢? 3 OnItemClick又是怎样被调用的呢

Eoeclient源代码分析---SlidingMenu的使用

Eoeclient源代码分析及代码凝视 使用滑动菜单SlidingMenu,单击滑动菜单的不同选项,能够通过ViewPager和PagerIndicator显示相应的数据内容. 0  BaseSlidingFragmentActivity.java 主要函数: (1)showMenu() /** * Opens the menu and shows the menu view.*/ public void showMenu() { showMenu(true); } (2)showContent

Robotium原则的实施源代码分析

从前面的章节<Robotium源代码分析之Instrumentation进阶>中我们了解到了Robotium所基于的Instrumentation的一些进阶基础.比方它注入事件的原理等,但Robotium作为一个測试框架.其功能远不止于仅仅是方便我们注入事件,其应该还包括其它高级的功能,參照我们前面其它框架如MonkeyRunner,UiAutomator和Appium的源代码分析,我们知道一个移动平台自己主动化測试框架的基本功能除了事件注入外起码还应该有控件获取的功能. 所以,这篇文章我们主

Android应用程序组件Content Provider的启动过程源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6963418 通过前面的学习,我们知道在Android系统中,Content Provider可以为不同的应用程序访问相同的数据提供统一的入口.Content Provider一般是运行在独立的进程中的,每一个Content Provider在系统中只有一个实例存在,其它应用程序首先要找到这个实例,然后才能访问它的数据.那么,系统中的Conten

Java中arraylist和linkedlist源代码分析与性能比較

Java中arraylist和linkedlist源代码分析与性能比較 1,简单介绍 在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arraylist和linkedlist的性能. 2,arraylist源代码分析 Arraylist底层的数据结构是一个对象数组.有一个size的成员变量标记数组中元素的个数,例如以下图: * The array buffer into which the elements of the ArrayLis

转:RTMPDump源代码分析

0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://.也提供 Android 版本. 最近研究了一下它内部函数调用的关系. 下面列出几个主要的函数的调用关系. RTMPDump用于下载RTMP流媒体的函数Download: 用于建立网络连接(NetConnect)的函数Connect: 用于建立网络流(NetStream)的函数 rtmpdump源代码

Kafka SocketServer源代码分析

Kafka SocketServer源代码分析 标签: kafka 本文将详细分析Kafka SocketServer的相关源码. 总体设计 Kafka SocketServer是基于Java NIO来开发的,采用了Reactor的模式,其中包含了1个Acceptor负责接受客户端请求,N个Processor负责读写数据,M个Handler来处理业务逻辑.在Acceptor和Processor,Processor和Handler之间都有队列来缓冲请求. kafka.network.Accepto

pomelo源代码分析(一)

千里之行始于足下,一直说想了解pomelo,对pomelo有兴趣,但一直迟迟没有去碰,尽管对pomelo进行源代码分析,在网络上肯定不止我一个,已经有非常优秀的前辈走在前面,如http://golanger.cn/,在阅读Pomelo代码的时候,已经连载到了11篇了,在我的源代码分析參考了该博客,当然,也会添?我对pomelo的理解,借此希望能提高一下自己对node.js的了解和学习一些优秀的设计. 开发环境:win7 调试环境:webstorm5.0 node.js版本号:v0.8.21 源代