为了节约你的时间,上面的图是整个文章的最终图,包括了以下部分问题的答案。
目录
3.ListView的回收机制是怎么样的?为什么可以显示100个View而不崩呢?
0.基本使用
获取ListView视图对象,设置adapter。
ListView lv = new ListView(context);
lv.setAdapter(new SimpleAdapter);
1.为什么需要使用Adapter?
ListView集成自absListView,同级的还有GridView。实际上我们可以发现,ListView是一个ViewGroup,提供把每个子View按照纵向布局在一起,然后提供滑动和fling功能。
从下面的图我们可以看到,左边是ListView,右边是data,中间是adapter,在这里ListView并不关心数据(data),是从数据库的cursor获取还是是从数组里面获取,我们只需要通过适配器Adapter统一一个协议就行。
试想一下不管是GridView还是ListView又或者是RecyclerView,无一不是需要知道总共几个子View,获取每个子View的视图,如果有多种类型的子View,还需要ItemViewType。所以我们其实就可以定义几个方法来获取这几个值,你看getView(获取子视图)、getCount(总共有几个子视图)、getItemViewType(每个子视图的type),这几个方法熟悉吗??我们实现这几个接口就能用adapter适配数据了。
那么有同学说,既然adapter隔离了数据,那么数据变动刷新ListView怎么操作呢?
你看1.1 register先注册观察者、1.2 notifyDataSetChanged 1.3 notifyChanged 不是典型的观察者模式吗? 这样就实现了adatper通知ListView刷新的功能了。
RecycleBin是什么?
RecycleBin是用于ListView子元素的缓存。里面有一个View[] mActiviesViews和ArrayList<View>[] mScrapViews。mActiviesViews用于存放ListView在屏幕内的对象,mScrapViews用于存放ListView移出屏幕的对象。注意mScrapViews是一个数组,索引是ItemType,元素是ArrayList<View>,所以说视图是按照ItemType为维度回收的,所以复用也是ItemType维度复用的。
图片左边是RecycleBin,右边是ListView,ListView中的所有元素,都是存在mActiviesViews里面一份的,所以当ListView刷新时,可以很快速的从内存中取出View来布局。当ListView上滑并且元素0完全移出屏幕时,会回收到RecycleBin的mScrapViews里面的ItemType类型为索引的ArrayList里面。
2.ListView的绘制过程是怎样的?
ListView也是ViewGroup,所以它的流程也是measure、layout、draw。ViewGroup的measure里面其实就是调用子布局的mesure,没什么特殊的。draw的话,其实也是调用子布局的绘制方法。所以我们分析layout过程,layout过程分为2种情况。
- 第一次layout。第一次layout,在RecycleBin获取不到mActiviesViews缓存,所以调用getView()直接朝adapter要View,要来了View后,然后逐个layout布局。
- 第N次layout。在RecycleBin获取到mActiviesViews缓存,然后逐个layout布局
3.ListView的回收机制是怎么样的?为什么可以显示100个View而不崩呢?
看图!!!
当我们向上滑动时,ListView的onTouchEvent中的move判断条件调用,判断元素0的getBottom()小于滑动距离,也就是元素0即将移出屏幕,这个时候ListView认为元素0没有用了&#x