android ListView 在初始化时多次调用getView()原因分析
今天在做一个功能:在初始化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()原因分析的更多相关文章
- 在jsp页面中设置了远程验证,在初始化时必须预先调用一次。
参考链接:http://code.taobao.org/p/sztaotao/diff/5/trunk/code/src/main/webapp/webpage/modules/sys/roleFor ...
- Android ListView无数据项时提示
只需要调用在代码中调用setEmptyView(View emptyView)设置ListView为空时显示这个TextView即可. 布局文件 <?xml version="1.0& ...
- Android Camera开发:周期性循环自动聚焦auto focus挂掉原因分析(preview is not enabled)
参考:Android Camera开发:扫描二维码,周期性循环自动聚焦auto focus挂掉原因分析(preview is not enabled) 最近做Android人脸识别时,camera在自 ...
- Android 学习笔记之WebService实现远程调用+内部原理分析...
PS:终于可以抽出时间写写博客了,忙着学校的三周破实训外加替考...三周了,没怎么学习...哎... 学习内容: 1.WebService 实现远程方法的调用 什么是WebService... ...
- mysql_init调用卡住原因分析
有同学做类似如下的操作: class X { public: X() // 类X的构造函数ctor { _mysql_handler = mysql_init(NULL); } }; // 定义类X的 ...
- Android 4.X 系统加载 so 失败的原因分析
1 so 加载过程 so 加载的过程可以参考小米的系统工程师的文章loadLibrary动态库加载过程分析 2 问题分析 2.1 问题 年前项目里新加了一个 so库,但发现native 方法的找不到的 ...
- Android的setVisibility(View.GONE)无效的问题及原因分析(转)
出现这种情况很可能是因为设置了animation,并且调用了setFillAfter(true),这就会导致setVisibility无效,只需要调用一下clearAnimation()方法或者去掉s ...
- Android的setVisibility(View.GONE)无效的问题及原因分析
出现这种情况很可能是因为设置了animation,并且调用了setFillAfter(true),这就会导致setVisibility无效,只需要调用一下clearAnimation()方法或者去掉s ...
- Pycharm下同一目录的py文件不能相互调用的原因分析
1.首先确保所在目录是Python Package而不是一般的New Stratch File Python Package下有__init___.py或自己建空的__init___.py 2.pyc ...
随机推荐
- jsp链接sql数据库
Connection 参数//这个参数用来执行链接数据库的操作 String 参数2="com.microsoft.sqlserver.jdbc.SQLServerDriver"; ...
- [技巧篇]16.MyEclipse2014安装SVN插件,在线安装
这两天想做点东西,但是现在流行的是git,但是军哥的项目是托管到阿里的svn代码当中,所以没有办法,还需要弄SVN,这里不将什么安装SVN等东西 我要求的就是快速入门而已,仅此而已,我安装成功,过程很 ...
- centos7下使用yum安装redis
centos7下使用yum安装Redis 第一步:安装 yum –y install redis 第二步:启动 systemctl start redis.service 第三步:设置开机启动 sys ...
- 多线程复习 Rlock ,Condition,Semaphore
#对于io操作来说,多线程和多进程性能差别不大 #1.通过Thread类实例化 import time import threading def get_detail_html(url): print ...
- centos6.8+openvpn实现账户密码连接(通过端口映射的方式)
#搭建openvpn(编译安装) 初始化环境 #update epel mirror yum install wget -y cd /etc/yum.repos.d && rm -rf ...
- Eclipse导入Java工程导入错误
1.在一台电脑A上用Eclipse新建的Java工程,换了一台电脑B,再用Eclipse导入时却出现了错误,工程显示红色叹号,并有如下两个错误提示: The project cannot be bui ...
- [BZOJ2440]完全平方数解题报告|莫比乌斯函数的应用
完全平方数 小 X 自幼就很喜欢数.但奇怪的是,他十分讨厌完全平方数.他觉得这些数看起来很令人难受.由此,他也讨厌所有是完全平方数的正整数倍的数.然而这丝毫不影响他对其他数的热爱. 这天是小X的生日 ...
- VMware 12安装虚拟机Mac OS X 10.10不能上网问题
1:从本机中选择打开连接网络,选择本地连接.如果是无线网可以选择无线网. 1: 2: 控制面板--->网络和共享中心 2:选择属性,点击共享按钮. 3:将internet连接共享下面选项都选中 ...
- idea 调试远程tomcat
# ----- Execute The Requested Command ----------------------------------------- JAVA_OPTS="-age ...
- linux c 执行新程序
学习进程时,linu c上说新开的进程一般要执行另外一个程序,同时与父进程执行同一个程序没有意义 如下是如何执行一个新的程序 使用exec函数簇 exec函数簇包含如下函数