AndroidはListViewに画像を表示する(錯乱点滅の問題を繰り返す)
AndroidはListViewに画像を表示する(錯乱点滅の問題を繰り返す)
1、原因分析
ListView itemキャッシュメカニズム:
パフォーマンスを向上させるために、ListViewは行item(対応する行)をキャッシュします.
ListViewは、adapterのgetView関数によって各行のitemを取得する.
スライド中
a.ある行のitemが画面から滑り出した場合、そのitemがキャッシュ内にない場合、putはキャッシュに入り、そうでない場合、キャッシュを更新する.
b.画面にスライドする行itemを取得する前に、キャッシュに使用可能なitemがあるかどうかを判断し、ある場合はconvertViewパラメータとしてadapterのgetViewに渡します.
これにより,次のようなgetView書き方がキャッシュを活用してListViewの性能を大幅に向上させることができる.数万行itemでも最大inflateの回数はnで、
nは、一画面で最大ListView行itemを表示する個数である.
これにより、パフォーマンスが向上しますが、他の問題も発生します.
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の識別と一致するかどうかを比較し,一致すると表示され,そうでなければ処理を行わない.
andbaseの実装コード:
andbaseの紹介:http://blog.csdn.net/menglele1314/article/details/46422409
ダウンロード:http://download.csdn.net/detail/menglele1314/8786989
1、原因分析
ListView itemキャッシュメカニズム:
パフォーマンスを向上させるために、ListViewは行item(対応する行)をキャッシュします.
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、解決方法
以上の解析から,錯乱の原因は非同期ロードとオブジェクトの多重化によるものであることが分かったが,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.type = type;
item.imageUrl = url;
final
String cacheKey = AbImageCache
.getCacheKey(item.imageUrl, item.width, item.height, item.type);
item.bitmap = AbImageCache.getBitmapFromCache(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.equals(imageView.getTag())){
loadingView.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);
}
// imageView url , set,
// , View
if
(bitmap!=
null
&& imageUrl.equals(imageView.getTag())){
if
(D) Log.d(TAG,
" , :"
+imageUrl);
imageView.setImageBitmap(bitmap);
}
else
{
if
(errorImage !=
null
&& imageUrl.equals(imageView.getTag())){
imageView.setImageDrawable(errorImage);
}
}
}
});
if
(D) Log.d(TAG,
" , :"
+url);
mAbImageDownloadPool.execute(item);
}
else
{
if
(loadingView !=
null
){
loadingView.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);
}
imageView.setImageBitmap(item.bitmap);
}
}
andbaseの紹介:http://blog.csdn.net/menglele1314/article/details/46422409
ダウンロード:http://download.csdn.net/detail/menglele1314/8786989