私のアプリにはListView
、カスタムを使用してCursorAdapter
データをロードする があり、基本的にImageView
とTextView
です。AsyncTask
問題は、最初はすべての画像が正しいテキストに割り当てられていますが、すばやく上下にスクロールすると、テキストごとにランダムな画像がバインドされます。CursorAdapter を使用ViewHolder
しているため、 here を使用できないため、この問題を解決するにはどうすればよいですか?
ここに私のサンプルコードがあります:
public class MyAdapter extends CursorAdapter {
private LayoutInflater mLayoutInflater;
@SuppressWarnings("unused")
private Context mContext;
public MyAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
}
public void bindView(View view, Context context, Cursor cursor) {
String title = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.TITLE));
String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
TextView text = (TextView)view.findViewById(R.id.txtTitle);
text.setText(title);
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri uri = ContentUris.withAppendedId(sArtworkUri, Integer.valueOf(album_id));
new MyImageLoader(context,view).execute(uri);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mLayoutInflater.inflate(R.layout.row, parent, false);
}
private class MyImageLoader extends AsyncTask<Uri, Void, Bitmap>{
Context context;
View view;
MyImageLoader(Context context,View view){
this.context = context;
this.view = view;
}
@Override
protected Bitmap doInBackground(Uri... uri) {
ContentResolver res = context.getContentResolver();
InputStream in = null;
try {
in = res.openInputStream(uri[0]);
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap artwork = BitmapFactory.decodeStream(in);
return artwork;
}
protected void onPostExecute(Bitmap bmp){
ImageView iv = (ImageView)view.findViewById(R.id.imgIcon);
if(bmp!=null)
//iv.setImageBitmap(bmp);
iv.setImageBitmap(Bitmap.createScaledBitmap(bmp, 100, 100, false));
}
}
}
更新: setTag メソッドを適用したところ、シャッフルが少なくなりましたが、速くスクロールすると、正しい画像が読み込まれるまで古い画像が 1 秒間表示されたままになります。新しいコードは次のとおりです。
public void bindView(View view, Context context, Cursor cursor) {
String title = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.TITLE));
String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
ImageView iv = (ImageView)view.findViewById(R.id.imgIcon);
TextView text = (TextView)view.findViewById(R.id.txtTitle);
text.setText(title);
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri uri = ContentUris.withAppendedId(sArtworkUri, Integer.valueOf(album_id));
// *****TAG SET*****
iv.setTag(uri);
//***PASSING BOTH URI AND IMAGEVIEW TO CONSTRUCTOR***
new MyImageLoader(context,view,iv,uri).execute(uri);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = mLayoutInflater.inflate(R.layout.row, parent, false);
//v.setTag(R.id.imgIcon, v.findViewById(R.id.imgIcon));
return v;
}
private class MyImageLoader extends AsyncTask<Object, Void, Bitmap>{
Context context;
View v;
ImageView iv;
Uri u;
MyImageLoader(Context context,View v,ImageView iv,Uri u){
this.context = context;
this.v = v;
this.iv = iv;
this.u = u;
}
@Override
protected synchronized Bitmap doInBackground(Object... param) {
ContentResolver res = context.getContentResolver();
InputStream in = null;
try {
Uri uri= (Uri)param[0];
in = res.openInputStream(uri);
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap artwork = BitmapFactory.decodeStream(in);
return artwork;
}
protected void onPostExecute(Bitmap bmp){
if(bmp!=null)
{ ImageView iv = (ImageView)v.findViewById(R.id.imgIcon);
if(iv.getTag().toString().equals(u.toString()))
iv.setImageBitmap(Bitmap.createScaledBitmap(bmp, 100, 100, false));
}
}
}
更新:バックグラウンド タスクを呼び出す前にプレースホルダー イメージを設定すると、はるかに良くなります。