ListView 加载数据原理及列表项过多出现空指针

来源:互联网 发布:国家规定加班工资算法 编辑:程序博客网 时间:2024/06/05 08:02

这两天写了一个程序,在其中使用了ListView ,使用过程中发现了一些没见过的异常情况。查了资料后才发现是跟ListView的加载方式有关。故写了一个小程序来测试:

代码如下:



运行结果:


点击按钮后,日志文件输出:


 

运行结果正确。

但是,如果把列表项的字体设置为40sp,使得无法同时显示出所有的列表项时,即:


这个时候再点击按钮,发现出现了异常:

 

出现了空指针异常。查了很多资料,发现与ListView的加载数据的方式有关。

ListView的工作原理如下:

                 ListView 针对每个item,要求 adapter “返回一个视图”(getView),也就是说ListView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到ListView的长度,然后根据这个长度,调用getView()一行一行的绘制ListView的每一项。如果你的getCount()返回值是0的话,列表一行都不会显示,如果返回1,就只显示一行。返回几则显示几行。如果我们有几千几万甚至更多的item要显示怎么办?为每个Item创建一个新的View?不可能!!!实际上Android早已经缓存了这些视图,大家可以看下下面这个截图来理解下,这个图是解释ListView工作原理的最经典的图了大家可以收藏下,不懂的时候拿来看看,加深理解,其实Android中有个叫做Recycler的构件,顺带列举下与Recycler相关的已经由Google做过N多优化过的东东比如:AbsListView.RecyclerListener、ViewDebug.RecyclerTraceType等等,要了解的朋友自己查下,不难理解,下图是ListView加载数据的工作原理:

 

下面简单说下上图的原理:

如果你有几千几万甚至更多的选项(item)时,其中只有可见的项目存在内存(内存内存哦,说的优化就是说在内存中的优化!!!)中,其他的在Recycler中

ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的

当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图

 

 

所以当ListView 的列表项过多而无法全部显示时,这时没显示出来的那部分的列表项无法获取,也就是说用ListView.getChildAt(position)获得的将是null,因为安卓在加载ListView时,只在内存中创建了显示出来的那几个列表项,其他列表项没有加载到内存。

 

附带:

如果在AlertDialog中将自定义View设置为ListView,那么无法为ListView的列表项添加响应事件,即使ListView绑定了setOnItemClickListener()。如果想在对话框中使用列表,应该使用setMultiChoiceItems()或者setSingleChoiceItems()方法。


参考文章:http://mzh3344258.blog.51cto.com/1823534/889879

0 0
原创粉丝点击