分享

Android ListView中item view重复使用带来的问题

 guitarhua 2016-05-16

本文主要介绍ListView中item view的重复使用、可能带来的出错情况以及解决方案

 

1、为什么item View重复使用及如何重复使用

熟悉ListView的朋友都知道,在ListView的每个item需要花较大的时间进行渲染(比如需要网络获取数据、图片)时,为了使得ListView能够平滑的上下滑动,需要对listView的adapter做一些性能优化,比如数据(图片)异步加载、重复使用item的view

 

其中item的重复使用代码如下

  1. @Override  
  2. public View getView(int position, View convertView, ViewGroup parent) {  
  3.     if (convertView == null && context != null) {  
  4.         convertView = inflater.inflate(R.layout.list_activity, null);  
  5.     }  
  6.     ……  
  7. }  

可以发现上面主要通过判断convertView若不为空进行重复使用,节省资源加载和创建的时间。然后这种重用之前的convertView会对当前的显示有一定影响

 

2、可能出错情况

a、convertView包含TextView

之前的convertView会显示某个textView,但当前我并不需要显示了没有问题,而因为重用会导致仍会显示。

 

b、convertView包含ImageView,且异步设置ImageView中ImageResource时的问题

调试adapter的getView函数就会发现,头3个item都是重用第1个item的,所以若异步修改第2和第3个item的imageView第1个也会被修改,导致第1个item的imageView不断闪烁

我的补充:

这种情况发生的原因是因为ListView没办法确定它一次需要实例化多少个 convertView,即调用多少次getView方法。而导致这样的结果可能有以下原因:

1、你自己重写的ListView在实例化以后直接使用,而没有给它指定高度和宽度。

2、将ListView布局在xml中高度值指定为了Wrap_Content

3、将ListView布局到一个父组件,ListView本身的height是fillParent,但是父类组件在其父组件中高度为Wrap_Content 等

如:

  1.      .....省略以上  
  2.      android:id="@+id/all"  
  3.         />  
  4.       
  5. </RelativeLayout>  
  6.   
  7. <LinearLayout   
  8.     android:layout_width="fill_parent"  
  9.     android:layout_height="<strong>wrap_content</strong>"  
  10.     >  
  11.     <ListView   
  12.          android:layout_width="fill_parent"  
  13.         android:layout_height="<strong>fill_parent</strong>"  
  14.         ></ListView>  
  15. </LinearLayout>  
  16.   
  17. /LinearLayout>  


c、convertView包含TextView ,且异步设置 TextView中图片时的问题

在textView中使用setCompoundDrawablesWithIntrinsicBounds添加图片,若第3个item 的textView异步添加了图片,第1个也会相应被加上

 

具体原因还没debug出来,暂时的解决方法有两个

3、解决方案

a、正确性优先,去除性能优化  ===== 我不大赞成,以上所有的出错方案都可以通过调整逻辑来达到理想效果并且保持性能

即不再重用convertView,每次重新赋值

  1. @Override  
  2. public View getView(int position, View convertView, ViewGroup parent) {  
  3.     convertView = inflater.inflate(R.layout.list_activity, null);  
  4.     ……  
  5. }  
 

b、初始化每个Item View中的出错元素

比如对于可能出错情况a的解决如下:

  1. @Override  
  2. public View getView(int position, View convertView, ViewGroup parent) {  
  3.     if (convertView == null && inflater != null) {  
  4.         convertView = inflater.inflate(R.layout.status_activity, parent, false);  
  5.     }  
  6.       
  7.     TextView tx = (TextView)convertView.findViewById(R.id.contentTextView);  
  8.     if (contentList.get(position) == null) {  
  9.         tx.setVisibility(View.GONE);  
  10.     } else {  
  11.         ……  
  12.     }  
  13. }  

其中if (contentList.get(position) == null) 即表示消除之前的convertView的影响。

其他元素初始设置类似,如ImageView的ImageResource。

 

这种方法对于很多View需要初始化时较麻烦,若出错view太多还是使用第一种解决方案方便些,毕竟很多时候性能不会那么差。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多