Android中ListView异步加载图⽚错位、重复、闪烁问题
分析及解决⽅案
Android ListView异步加载图⽚错位、重复、闪烁分析以及解决⽅案,具体问题分析以及解决⽅案请看下⽂。
我们在使⽤ListView异步加载图⽚的时候,在快速滑动或者⽹络不好的情况下,会出现图⽚错位、重复、闪烁等问题,其实这些问题总结起来就是⼀个问题,我们需要对这些问题进⾏ListView的优化。
⽐如ListView上有100个Item,⼀屏只显⽰10个Item,我们知道getView()中convertView是⽤来复⽤View对象的,因为⼀个Item的对应⼀个View对象,⽽ImageView控件就是View对象通过findViewById()获得的,⽽我们在复⽤View对象时,同时这个ImageView对象也被复⽤了。⽐如第11个Item的View复⽤了第1个Item View对象,那么ImageView就同时被复⽤了,所以当图⽚没下载出来,这个ImageView(第11个Item)显⽰的数据就是复⽤(第1个Item)的数据。
1:Item图⽚显⽰重复
这个显⽰重复是指当前⾏Item显⽰了之前某⾏Item的图⽚。
⽐如ListView滑动到第2⾏会异步加载某个图⽚,但是加载很慢,加载过程中ListView已经滑动到了第14⾏,且滑动过程中该图⽚加载结束。第2⾏已不在屏幕内,根据上⾯介绍的缓存原理,第2⾏的View对象可能被第14⾏复⽤,这样我们看到的就是第14⾏显⽰了本该属于第2⾏的图⽚,造成显⽰重复。
2. Item图⽚显⽰错乱
这个显⽰错乱是指某⾏Item显⽰了不属于该⾏Item的图⽚。
跟上⾯的原因⼀样。
3. Item图⽚显⽰闪烁
上⾯介绍的另外⼀种情况,如果第14⾏图⽚⼜很快加载结束,所以我们看到第14⾏先显⽰了复⽤的第2⾏的图⽚,⽴马⼜显⽰了⾃⼰的图⽚进⾏覆盖造成闪烁错乱。
解决⽅案:
通过上⾯的分析我们知道了出现错乱的原因是异步加载及对象被复⽤造成的,如果每次getView能给对象⼀个标识,在异步加载完成时⽐较标识与当前⾏Item的标识是否⼀致,⼀致则显⽰,否则不做处理即可。
原理:⾸先给ImageView设置⼀个Tag,这个Tag中设置的是图⽚的url,然后在加载的时候取得这个url和要加载那position中的url对⽐,如果不相同就加载,相同就是复⽤以前的就不加载了。
Android在ListView显⽰图⽚(重复错乱闪烁问题)
1、原因分析
ListView item缓存机制:
为了使得性能更优,ListView会缓存⾏item(某⾏对应的View)。
ListView通过adapter的getView函数获得每⾏的item。
滑动过程中
a. 如果某⾏item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存;
b. 获取滑⼊屏幕的⾏item之前会先判断缓存中是否有可⽤的item,如果有,做为convertView参数传递给adapter的getView。这样,如下的getView写法就可以充分利⽤缓存⼤⼤提升ListView的性能。即便上万个⾏item,最多inflate的次数为n,
n为⼀屏最多显⽰ListView ⾏item的个数。
@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 ( ) ;
}
}
这样提升了性能,但同时也会造成另外⼀些问题:
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、解决⽅法listview控件在哪里
通过上⾯的分析我们知道了出现错乱的原因是异步加载及对象被复⽤造成的,如果每次getView能给对象⼀个标识,在异步加载完成时⽐较标识与当前⾏item的标识是否⼀致,⼀致则显⽰,否则不做处理即可。
andbase中的实现代码:
/**
* 显⽰这个图⽚,解决了列表问题.
* 列表问题:滑动过程中,getView的imageView会重复利⽤,导致图⽚会串位
* @param imageView 显得的View
* @param url the url
* @return
*/
public void display( final ImageView imageView,String url) {
if (AbStrUtil.isEmpty(url)){
if (noImage != null ){
if (loadingView != null ){
loadingView.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);
}
imageView.setImageDrawable(noImage);
}
return ;
}
//设置下载项
final AbImageDownloadItem item = new AbImageDownloadItem();
//设置显⽰的⼤⼩
item.width = width;
item.height = height;
//设置为缩放
item.imageUrl = url;
final String cacheKey = AbImageCache
.getCacheKey(item.imageUrl, item.width, item.height, pe);
item.bitmap = BitmapFromCache(cacheKey);
//if(D) Log.d(TAG, "缓存中获取的"+cacheKey+":"+item.bitmap);
//设置标记
imageView.setTag(url);
if (item.bitmap == null ){
//先显⽰加载中
if (loadingView!= null ){
loadingView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.INVISIBLE);
} else if (loadingImage != null ){
imageView.setImageDrawable(loadingImage);
}
//下载完成后更新界⾯
item.setListener( new AbImageDownloadListener() {
@Override
public void update(Bitmap bitmap, String imageUrl) {
//未设置加载中的图⽚,并且设置了隐藏的View
if (loadingView != null && imageUrl.Tag())){
loadingView.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);
}
//要判断这个imageView的url有变化,如果没有变化才set,
//有变化就取消,解决列表的重复利⽤View的问题
if(bitmap!=null&& imageUrl.Tag())){
if (D) Log.d(TAG, "图⽚下载,设置:" +imageUrl);
imageView.setImageBitmap(bitmap);
} else {
if (errorImage != null && imageUrl.Tag())){
imageView.setImageDrawable(errorImage);
}
}
}
});
if (D) Log.d(TAG, "图⽚下载,执⾏:" +url);
} else {
if (loadingView != null ){
loadingView.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);
}
imageView.setImageBitmap(item.bitmap);
}
}
以上内容就是Android中ListView异步加载图⽚错位、重复、闪烁问题分析及解决⽅案,希望对⼤家今后的⼯作和学习有所帮助。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。