我直接从mp3上加载图片,并在我的应用程序中将它们与歌曲标题一起显示。为了平滑过程我使用AsyncTask并在后台加载图像。如果我慢慢滚动,图像会以正确的顺序显示。但是,如果我快速向上和向下滚动,则图像会混乱2-3秒(如显示的顺序不正确)。 2-3秒后,订单再次变为正常。我怎么能避免这个?这是我的代码:
public class TestAcitivity extends SherlockListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActionBar ab = getSupportActionBar();
Uri sourceUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String [] proj = {MediaStore.Audio.Media._ID,MediaStore.Audio.Media.TITLE,MediaStore.Audio.Media.ALBUM_ID};
CursorLoader cursorLoader = new CursorLoader(this, sourceUri,proj,
null, null, MediaStore.Audio.Media.TITLE);
Cursor cursor = cursorLoader.loadInBackground();
ListView lv = getListView();//(ListView)this.findViewById(R.id.listview);
lv.setAdapter(new MyAdapter(this, cursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));
}
}
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);
if(Long.valueOf(album_id)>0)
{
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) {
View v = mLayoutInflater.inflate(R.layout.row, parent, false);
//bindView(v, context, cursor);
return v;
}
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(Bitmap.createScaledBitmap(bmp, 100, 100, false));
}
}
}
我正在使用自定义CursorAdapter
加载AsyncTask
中的位图。
答案 0 :(得分:0)
它可能与控制受异步更新影响的列表的排序顺序有关。它可能是列表项大小的快速变化,使列表视图的呈现代码混乱。一个建议是将默认(可能是黑色)图像直接添加到相同大小的每个列表项。然后当真实图像进来时,只需更换黑色图像。
编辑:似乎这个问题是由Android回收ViewItem /行引起的,而且这个问题与异步任务相混淆。有关更多详细信息和一些解决方案,请参阅此StackOverflow question。
答案 1 :(得分:0)
Hack_on是正确的。其中一位Andorid工程师在博客中讨论了这个问题:
但是,特定于ListView的行为会显示我们的问题 目前的实施。的确,出于内存效率的原因, ListView回收用户滚动时显示的视图。 如果一个人翻转列表,则会使用很多给定的ImageView对象 倍。每次显示时,ImageView都会正确触发 图像下载任务,最终将改变其图像。那么在哪里 是问题吗?与大多数并行应用程序一样,关键问题是 在订购中。在我们的例子中,不保证下载 任务将按照启动顺序完成。结果 是最终显示在列表中的图像可能来自a 上一个项目,它恰好花了更长的时间下载。 如果您下载的图像被绑定一次,那么这不是问题 所有给予ImageViews,但让我们解决它的常见情况 它们用在列表中。
这是链接,他也提供了解决方案:
http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html