我相信做过Android应用程序开发或多或少都遇到了这个问题。或者是在ListView数据损坏幻灯片事件。要么GridView数据损坏幻灯片事件。

让我们来看看一个网友写的文章,个人感觉还不错的文章:

Android ListView滑动过程中图片显示反复错位闪烁问题解决

主要分析Android ListView滚动过程中图片显示反复、错乱、闪烁的原因及解决方法,顺带提及ListView的缓存机制。

1、原因分析
ListView item缓存机制:为了使得性能更优。ListView会缓存行item(某行相应的View)。ListView通过adapter的getView函数获得每行的item。滑动过程中,

a. 假设某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存。
b. 获取滑入屏幕的行item之前会先推断缓存中是否有可用的item,假设有,做为convertView參数传递给adapter的getView。

更详细可见源代码ListView.obtainView。

这样,例如以下的getView写法就能够充分利用缓存大大提升ListView的性能。即便上万个行item。最多inflate的次数为n,n为一屏最多显示ListView 行item的个数。

ListView Adapter getView写法

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.list_item, null);
        holder = new ViewHolder();
        ……
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }
}
/**
* ViewHolder
*
* @author trinea@trinea.cn 2013-08-01
*/
private static class ViewHolder {
    ImageView appIcon;
    TextView  appName;
    TextView  appInfo;
}

这样提升了性能。但同一时候也会造成另外一些问题:

a. 行item图片显示反复
这个显示反复是指当前行item显示了之前某行item的图片。

比方ListView滑动到第2行会异步载入某个图片,可是载入非常慢,载入过程中listView已经滑动到了第14行,且滑动过程中该图片载入结束。第2行已不在屏幕内,依据上面介绍的缓存原理,第2行的view可能被第14行复用,这样我们看到的就是第14行显示了本该属于第2行的图片。造成显示反复。

b. 行item图片显示错乱
这个显示错乱是指某行item显示了不属于该行item的图片。
比方ListView滑动到第2行会异步载入某个图片。可是载入非常慢。载入过程中listView已经滑动到了第14行。第2行已不在屏幕内。依据上面介绍的缓存原理,第2行的view可能被第14行复用,第14行显示了第2行的View,这时之前的图片载入结束,就会显示在第14行,造成错乱。

c. 行item图片显示闪烁
上面b的情况,第14行图片又非常快载入结束。所以我们看到第14行先显示了第2行的图片,立刻又显示了自己的图片进行覆盖造成闪烁错乱。

2、解决方法
通过上面的分析我们知道了出现错乱的原因是异步载入及对象被复用造成的。假设每次getView能给对象一个标识,在异步载入完毕时比較标识与当前行item的标识是否一致,一致则显示,否则不做处理就可以。
以下以使用ImageCache为ListView提供图片获取缓存为例,ListView中强烈推荐使用ImageCache。

首先在listview adapter的getView中加入

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
    ViewHolderholder;
    if(convertView==null){
        convertView=inflater.inflate(R.layout.list_item,null);
        holder=newViewHolder();
        ……
        convertView.setTag(holder);
    }else{
        holder=(ViewHolder)convertView.getTag();
    }
    ……
    // add tag for image, to compare it when image loaded finish
    imageView.setTag(imageUrl);
    // if not in cache, restore default
    if(!Cache.ICON_CACHE.get(imageUrl,imageView)){
        imageView.setImageDrawable(null);
    }
}

当中setTag表示设置标识,方便以下进行标志比对

1
if (!Cache.ICON_CACHE.get(imageUrl, imageView))

Cache.ICON_CACHE为ImageCache的实例。表示假设不在缓存内则设置drawable为null(当然你能够能够设置为你自己的默认资源),防止显示了之前某个行item的图片,攻克了a. 行item图片显示反复问题。

在ImageCache的OnImageCallbackListener的onGetSuccess函数中加入

Java
1
2
3
4
5
6
7
8
9
10
11

publicvoidonGetSuccess(StringimageUrl,DrawableimageDrawable,Viewview,booleanisInCache){
    // can be another view child, like textView and so on
    if(view!=null&&imageDrawable!=null){
        ImageViewimageView=(ImageView)view;
        // add tag judge, avoid listView cache and so on
        StringimageUrlTag=(String)imageView.getTag();
        if(ObjectUtils.isEquals(imageUrlTag,imageUrl)){
            imageView.setImageDrawable(imageDrawable);
        }
    }
};

在上面用String imageUrlTag = (String)imageView.getTag();取得之前设置的tag,然后和当前的url进行比較,假设相等则显示,攻克了b. 行item图片显示错乱。c. 行item图片显示错乱的两个问题。

当中ObjectUtils可见ObjectUtils@Github.

其它异步载入过程解决原理类似。

插一句:标题上我加了此文章的原文链接。

大家通过上面的文字能够发现,混乱的本质原因是因为使用了ViewHolder以及ListView的Item的缓存机制。所以在解决本类问题时也就分为两种方法:

(1)把上文中if(convertView==null){}else{holder=(ViewHolder)convertView.getTag() }给凝视 掉,然后数据混乱的问题就得以攻克了,可是这样问题尽管攻克了,应用程序性能就减少了。显然此种方法虽能解决这个问题,可是还是不建议使用。

(2)就是通过加入Tag标记,可是尽管是说加入Tag标记,每个应用程序加入Tag的方法不同。故在此无法给出一个统一的解决方法,仅仅能说一个统一的解决思路。比如:假设混乱的是一件商品的数量,能够把商品的数量暂时存到一个数组中,然后每次取值都从数组里取值即可了。事实上说白了,就是依据详细的情况new 一个对应的数组,来做数据的中转站。例如以下图情形:

在滑动时,我们会发现数量的值会发生混乱,或者在加减右图中的数字时,也会出现这种情况。

以下提供一个类似的方案。事实上对应的代码都是在你应用中的Adapter中改动。

首先声明一个数组用于存放数量:

private int [] tempNum;

然后在本Adapter的构造方法中初始化此数组:tempNum=new int[this.list.size()];

然后在getView方法中一定要有例如以下代码:mItemViewHolder.mTvNum.setTag(position);

mItemViewHolder.mTvNum.setText(tempNum[position]+"");

然后在加减时。也要把最新的数量存到数组里。例如以下:

<span style="white-space:pre">       </span>case R.id.menu_reduce_iv:mTextView=(TextView)v.getTag(R.id.menu_num_tv);num=Integer.valueOf(mTextView.getText().toString().trim());num--;tempNum[(Integer)mTextView.getTag()]=num;if(num<0){Toast.makeText(context, "亲,不能再减了,赶紧加加吧。", Toast.LENGTH_SHORT).show();}else{mTextView.setText( tempNum[(Integer)mTextView.getTag()]+"");}break;case R.id.menu_add_iv:mTextView=(TextView)v.getTag(R.id.menu_num_tv);num=Integer.valueOf(mTextView.getText().toString().trim());num++;tempNum[(Integer)mTextView.getTag()]=num;mTextView.setText(tempNum[(Integer)mTextView.getTag()]+"");break;

总之。在做此类处理时,一定要new一个数组,然后在混乱的地方一定要setTag。

大致就说到这里,鄙人才疏学浅,有不正确之处,望大家及时指出。转载请注明:http://blog.csdn.net/android_jiangjun/article/details/39924541

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Android在ListView滑动数据混乱相关推荐

  1. Android之 ListView滑动时不加载图片

    listview加载图片优化的功能, 在我们使用新浪微博的时候,细心的同学一定发现了,在滑动的过程中,图片是没有被加载的, 而是在滑动停止时,才加载图片了. 我们今天就做一个这样的效果吧. 我们先考虑 ...

  2. 九、android的ListView实现数据列表展示

    基于上一篇第八节的数据库操作为基础,对数据库中的内容在android界面上进行列表展示 1.工程结构: 列表显示示意图: 列表显示效果图: 2.界面的列表展示配置文件 item.xml: <?x ...

  3. Xamarin.Android 使用ListView绑定数据

    使用ListView进行数据绑定 第一步:新建一个类,用于存储显示字段. namespace ListViewDataBIndDemo {public class Person{public int ...

  4. android开发 listview 头部 轮播,listview添加的头部布局超过一屏头部内容显示不全...

    headView的实际高度超过一个屏幕,但是显示的结果只有一个屏幕,超过一个屏幕高度意外的部分显示不全. 只使用了listView.getRefreshable().addHeadView(headV ...

  5. android 之ListView分页效果以及从网络上加载数据一系列的综合运用

    数据分页策略: <1>:用多少查多少 <2>:全部查询出来,再进行分页处理 数据分页的有关算法: (1):起始索引值 = (当前页-1)*每页显示的记录数 (2):结束索引值 ...

  6. Android中ListView分页加载数据

    熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,我们今天就要讲一讲列表组件ListView加载数据的相关内容 ...

  7. android listview 滑动条显示_ListView详细介绍与使用

    前言介绍: 关于 ListView 我们大家都应该是非常的熟悉了,在 Android 开发中是经常用到的,今天就再来回顾一下,ListView 的使用方法,和一些需要优化注意的地方,还有日常开发过程中 ...

  8. (原创)使用AsyncTask(带修改线程池方式)+自定义ImageLoader+LRU算法对图片三级缓存及其显示优化(只有在ListView滑动停止的时候才去网络请求获取图片数据)

    前言: 以前看了些关于图片优化处理缓存比较全的视频(感谢慕风网),现在回顾觉得还是挺好的也就总结出来下,感觉针对图片做处理这块还真的用的比较多,本文章只要使用异步线程AsyncTask.自定义的Ima ...

  9. Android ListView滑动删除及响应事件详解

    目标:实现类似QQ,微信的消息列表滑动删除 具体操作: 1. 主页面布局 首先在布局文件(本例是activity_main.xml)中引入ListView控件,并指定id(如下代码中黑体部分). &l ...

最新文章

  1. 计算机和打印机的耗材管理,打印设备耗材余量知多少?多种途径实时掌握
  2. 深度学习之利用TensorFlow实现简单的卷积神经网络(MNIST数据集)
  3. r生成新的dataframe_2020-08-11R语言中dataframe与list的转换方法
  4. SAP CRM IBASE read header debug
  5. python自编信息加密函数_自定义Python加密算法
  6. 连接池和 Timeout expired异常【转】
  7. 15.深入理解Zend执行引擎(PHP5)
  8. namenode 无法启动之每次开机需要重新格式化-tmp
  9. Python是个什么鬼,为什么机械设计都要用到他?
  10. 软件维护集成价格估算
  11. 【学生网页设计作品 】关于HTML公益主题网页设计——谨防电信诈骗网
  12. Python中hashlib.sha1()和hashlib.MD5()哈希算法的区别
  13. SpringBoot之自定义starter
  14. DFS实现传教士野人渡河问题
  15. Flask项目之手机端租房网站的实战开发(一)
  16. hdu 6578 Blank dp
  17. 关于span设置宽高
  18. Translation idea插件
  19. 推荐一个文本编辑器-PilotEdit
  20. Webstorm2016安装激活

热门文章

  1. 如何获得Java中泛型类的类型参数?
  2. UVA 327 Evaluating Simple C Expressions
  3. [置顶] 2014年八大最热门IT技能
  4. adb logcat查看手机端日志
  5. ZOC7 for Mac连接CentOS7无法输入中文问题
  6. 一个mui+ajax+php的demo
  7. [leetcode] Bulb Switcher
  8. 剑指offer第41题 和为s的两个数
  9. cocos3 深入理解tank和子弹之间的关系
  10. WebConfig自定义节点并读取