在学习安卓UI控件的时候,发现ListView是在实际开发中会比较常用的一个控件,可以以列表的形式展示数据。但是学习时感觉它比别的控件使用起来要麻烦一些,因为需要设置适配器,然后通过适配器去访问数据。这不免让我对这种机制感到好奇,所以大概研究了一下Adapter以及ListView的大致工作流程。
引入Adapter主要是因为ListView需要展示很多数据,然而这些数据的形式是各种各样的(比如数组、游标等),如果ListView要负责适配数据扩展性就比较差。然后Adapter就是起到了ListView与数据源之间桥梁的作用。ListView只负责展示数据而让Adapter去访问数据源,同时因为Adapter有着统一的接口所以ListView并不需要额外的适配问题,适配问题交由Adapter实现不同的子类,由这些子类负责与特定数据源的适配。Android中适配器主要类型有ArrayAdapter,SimpleAdapter,SimpleCursorAdapter和自定义的Adapter。这里就列举一个自定义Adapter的例子,由它去研究一下Adapter的实现(这里的例子使用第一行代码中的示例)。
这里截取比较重要的地方的代码,ListView的大致工作流程就是新建一个Adapter(上面用一个自定义的Adapter来装配数据,它的构造需要this、每行的布局文件和数据源文件),把数据源列表传给这个Adapter,通过Adapter的getView()方法生成每一行对应的视图,最后通过ListView设置Adapter完成工作。不难发现Adapter的重点就在于这个getView()方法,接下来对这个方法进行一些简要的介绍。下面是getView方法的源码。
在getView()方法的参数中,第二个参数convertView是什么呢?这里先放上一张很经典的图
因为ListView一般数据量很大,所以为每一行创建一个View是不现实的做法。Android提供了一个叫做Recycler的控件进行视图的缓存,原理见上图。当某一行完全移出屏幕的可视区域时,这个Item的View会被加入到Recycler中,这就是convertView参数。getView()方法中先判断convertView是不是null,是的话新建,否则可以直接从Recycler中取出使用,然后在view中设置需要的新数据即可。就比如上图中一个屏幕最多能显示7条数据,所以开始的7条convertView都是null,所以生成了7个view。当继续往下滑动item1完全移出屏幕时这个view被加入到Recycler中,当item8进入屏幕时,此时检查Recycler中是否有可用的view,发现此时convertView不是null,就直接从Recycler中把view1取出赋上item8的数据即可。
这样就不难理解getView()方法了,position是指该视图在适配器数据中的位置,通过getCount和getItem来使用,通过position获取特定的数据源数据,然后生成对应一行的视图,然后交由ListView展示。
参考文献:
Android ListView工作原理完全解析,带你从源码的角度彻底理解
Android第一行代码