我相信做过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: 1. ListView通常有两个职责: 1.向布局填充数据 2.处理选择点击等操作 2.ListView的创建需要3个元素: 1. ListView中的每一列的View. 2. ...

  2. Android之ListView分页数据加载

    1.效果如下: 实例如下:  上图的添加数据按钮可以换成一个进度条  因为没有数据所以我加了一个按钮添加到数据库用于测试:一般在服务器拉去数据需要一定的时间,所以可以弄个进度条来提示用户: 点击加载按 ...

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

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

  4. android中listview滑动卡顿的原因

    导致Android界面滑动卡顿主要有两个原因: 1.UI线程(main)有耗时操作 2.视图渲染时间过长,导致卡顿 http://www.tuicool.com/articles/fm2IFfU 

  5. Android 自定义ListView 修改数据

    当我们修改了 自定义ListView,如何更新界面上的控件呢? 两种方法: 1 重新绑定adapter (不推荐) Adapter_InboundPO adapter =(Adapter_Inboun ...

  6. Android 中利用ViewFlipper 滑动屏幕切换页面,ListView展示数据

    首先新建一个Android项目,命名为ViewFlipperTest 如图:项目机构,本项目主要操作图中红色箭头标注的文件 1.HgroupAdapter.java文件代码↓主要实现listview数 ...

  7. android listView 滑动载入数据 该数据是服务端获取的

    package com.sunway.works.applycash; import java.util.ArrayList; import java.util.Calendar; import ja ...

  8. Android中ListView动态加载数据

    1. 引言: 为了提高ListView的效率和应用程序的性能,在Android应用程序中不应该一次性加载ListView所要显示的全部信息,而是采取分批加载策略,随着用户的滑动,动态的从后台加载所需的 ...

  9. 【Android】ListView监听上下滑动(判断是否显示返回顶部按钮

    设置滚动监听判断ListView的滚动方向同时获取屏幕高度.ListView实际高度,判断是否需要展示返回顶部按钮 package com.zihao.activity;   import java. ...

随机推荐

  1. C++设计模式--观察员

    概要 在软件构建过程中.我们须要为某些对象建立一种"通知依赖关系" --一个对象(目标对象)的状态发生改变,全部的依赖对象(观察者对象)都将得到通知.假设这种依赖关系过于紧密,将使 ...

  2. poj 3172 Scales 搜索

    其实这个题目要是注意到了题目的一点关键性的描述就会变得很简单,题意是给出的砝码是至少是前两个的和的,有了这一点,那么砝码的数量应该就在几十左右,这样的话适当剪枝的搜索是应该可以过的. #include ...

  3. Linux C语言写的超级简单port扫描器

    这个本来曾经也写过的,今天无聊复习下 再写一遍.简单的一塌糊涂,写的不咋地大家见谅哦!有空再加强 嘿嘿! #include <stdio.h> #include <stdlib.h& ...

  4. iPhone 6 首发无大陆,DevStore要去香港吗?

    iPhone 6 正式公布,微博已经被刷屏.iPhone 6 的各种信息都已经明了,先不说什么配置,什么设计,就说一点--iPhone6 首发地方是没有中国大陆的.这让我想起来最近參加的源代码大赛,这 ...

  5. 自己动手写CPU之第六阶段(2)——移动操作指令实现思路

    将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第21篇,我尽量每周四篇 6.2 移动操作指令实现思路 6.2.1 实现思路 这6条移动操作指令能够分为两类:一类是不涉及特殊 ...

  6. UML 之 序列图和协作图

    序列图(Sequence Diagram)     亦称为时序图或循序图,是一种UML行为图.它通过描写叙述对象之间发送消息的时间顺序显示多个对象之间的动态协作.它能够表示用例的行为顺序,当运行一个用 ...

  7. Windows Phone开发(13):如何规范用户的输入行为

    原文:Windows Phone开发(13):如何规范用户的输入行为 很多时候,我们对用户的操作或输入做一定程度的限制,以避免发生不必要的异常或错误,因此,对一些特殊的类型,进行输入限制是很有必要的. ...

  8. gc overhead limit exceeded eclipse错误解决方式

    在Eclipse打包的时候报错:gc overhead limit exceeded eclipse 原因是Eclipse默认配置内存太小须要更改安装Eclipse目录下的eclipse.ini文件. ...

  9. 第2周 页_SQL Server 中数据存储的基本单位

    原文:第2周 页_SQL Server 中数据存储的基本单位 上周通过探讨SQL Server如何执行一个查询奠定了基础.我也在那里提到页是8kb的缓存.今天我们对页进行进一步集中探讨,从性能调优角度 ...

  10. UDP议定书图像高速传输无损失程序

    下面的程序实现UDP没有图像数据的高速传输协议损耗,测试数据egtest01图片库,实现PC和图像的传输嵌入式结束.变速箱+读写速度可以达到10+M/S.考 server端程序 #include &l ...