android ListView 在初始化时多次调用getView()原因分析

转载 2015年07月06日 23:44:56

本文转自:http://www.cnblogs.com/linjzong/p/3494090.html

 今天在做一个功能:在初始化ListView时,把第一行背景置为黄色,同时保存第一行对象,用于在点击其他行时将该行重新置为白色。

if(position==0){
                convertView.setBackgroundColor(Color.YELLOW);
                lastconvertView=convertView;
            }

 

结果运行时发现第一行的颜色一直会是黄色而无法改变。调试了之后发现getView中 if(position==0) 居然会多次进入,最终导致的结果便是我最后一次取得的lastconvertView并非listview上面的第一行。网上查了之后发现原因是因为未固定listview的高度导致的,但是root cause却找不到说明。于是去翻阅了源码+大量调试,大概推算出了原因,在此记录。

首先是说明下ListView的显示机制,listview的机制是这样子的:

假如你有1000条数据,但是屏幕只能显示10条,那么当你第一次加载显示的时候,会先创建10个View,1-10,当你拖动Listview,使1隐藏而11显示的时候,系统会自动把填充1的View传递过来,注意看代码Adapter的getView方法

@Override
public View getView(final int position, View convertView, ViewGroup parent) 

这里的converView就是1的view,一般的做法会把这个view拿来复用,作为11的view。

 

当我们固定listview的高度时(fill_parent或直接固定高度),那么listview很容易就能计算出容器内可以显示多少行。但如果我们使用了“wrap_content”,只有在屏幕内控件完全加载后才知道到底能显示多少行数据时,ListView自身便会做一些尝试性计算。在源码中可以发现一些叫做onMeasure的方法,目测是做此用处(源码略显复杂,没读透)。

当listview计算出屏幕一共需要多少行后,如果listview自身高度不变,那么它的容纳的行数就不会变,使用getChildCount()可以得到它的最大行数。

再回到原来的问题,为什么最后一次取得的结果不是listview的第一行呢? 将listview设置为“wrap_content”后用下面的测试代码,看下输出。

复制代码
//获取当前listview的个数 相等输出个数和站点名 不相等输出个数和"无"
            if(listView.getChildCount() == position)
            {
                //child个数 当前position位置 +站名
                Log.i("", listView.getChildCount()+" "+position+" "+coordInfo.stationname);
            }
            else {
                //child个数 当前position位置+无
                Log.i("", listView.getChildCount()+" "+position+" "+"无");
            }
复制代码

在我的测试应用中,listview刚好可以放11个view,看下输出发现,listview在开始时,实例化了11个view进行填充,即前面10个“无”结尾的+第一个”客运中心“结尾的view,由此测量出了listview的容量。换句话说,这11个view都只是用于测量的临时view。另外在正是填充完之后,listview再次创建了11个临时view用于确认高度是否正确。而由于我的代码逻辑设计失误,在

进行到这一步时,由于position会再次等于0,因此会把一个临时的view赋值给lastconvertView。

到此原因找到,同时将listview的高度设为fill_parent后,问题解决。

 

另外说下网上说的另外一个解决方法

复制代码
if(parent.getchildcount() == position)
{
       正常情况下应该执行的代码
}
else
{
     这里就是多次加载的问题,可以不用理这里面的 代码,
}
复制代码

这个方法是不可行的,因为在不改变listview高度的情况下,listview的getchildcount()在加载完成后是固定的,position指的却是在adapter中的位置,当adapter的个数大于listview的容纳个数时,该判断条件不会成立,即滑动listview时,不会成立。


android ListView 在初始化时多次调用getView()原因分析

今天在做一个功能:在初始化ListView时,把第一行背景置为黄色,同时保存第一行对象,用于在点击其他行时将该行重新置为白色。 if(position==0){ ...
  • LAMP_zy
  • LAMP_zy
  • 2015年06月22日 22:33
  • 670

android listview 连续调用 getview多次问题分析及解决

当我们在使用listview的时候。有时候自定义adapter的时候,是不是会发现在getview里打印日志的时候,重复调用很多次?有时候4次。有的严重甚至到10次,当我们在listview中移动的时...

Android ListView getView多次不规律调用问题

今天偶然发现ListView的getView方法会执行多次,一共只有3个Item,getView却调用了n次,代码如下 @Override public View getView(int pos...
  • lxiin
  • lxiin
  • 2015年03月04日 19:28
  • 510

Android ListView优化之getView频繁多次调用与ViewHolder工作原理

Android中我们经常会用到ListView,然后ListView到底是如何通过ViewHolder去优化的? 1.常见的适配器中利用ViewHolder去优化ListView的代码 @Overri...

Android listview&gridview getview 方法多次调用问题解决方法 并附上单页加载实现问卷调查适配器源代码

一 、 关于listview 的问题     (1)情况一:      今天在改毕设代码的时候,突然发现一个奇怪的现象,就是在在定义的listview中有一个imageview和一个textvie...

ListView设置adapter时getView被多次调用

今天在做项目的时候,发现ListView在高度为wrap_content时,adater中的getView方法居然被调用了三次,于是在网上搜索 发现也有网友与我碰到的问题相同,但有的只是说把wrap...

创建ListView时getView()的多次调用

在使用ListView显示数据的时候,定义一个适配器,然后重写getView()方法,这时通过LOGCAT日志分析会发现getView()方法会被执行多次。通过上网查询资料得出 原因在于View在Dr...

解决ListView,Gallery的Adapter中由于布局问题导致的getView多次调用问题

由于布局很复杂,我的listview嵌套了好多层,导致adapter中getview方法调用了多达几百次!!!因为要计算很多次父控件的高度!!!而且在点击edittext控件时,弹出或者收回输入法的时...

关于ListView中getView被重复调用多次的问题

我用ListView显示数据时,自定义了一个适配器(extends ArrayAdapter),然后重写了getView方法,现在出现一个问题,就是这个getView()方法被重复调用了,比如我的_d...

关于ListView的getView方法被多次重复调用的问题

package com.pxy.demo.adapter; import java.util.ArrayList; import com.pxy.demo.R; import android.c...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android ListView 在初始化时多次调用getView()原因分析
举报原因:
原因补充:

(最多只允许输入30个字)