listview的getview方法为什么会调用三次
1个回答
2016-04-27
展开全部
今天在做一个功能:在初始化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+" "+"无");
}
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+" "+"无");
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询