图片使用AsyncTask的ListView中混杂了 [英] Images jumble up in ListView using AsyncTask

查看:116
本文介绍了图片使用AsyncTask的ListView中混杂了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我直接从MP3的加载图像,并与我的应用程序歌名一起显示它们。为了抚平我正在使用的AsyncTask和加载背景图像的过程。如果我慢慢滚动的图像出现在正确的顺序用歌声。不过,如果我快速向上和向下滚动,然后将图像混杂了2-3秒(如出现不正确的顺序)。 2-3秒后再次顺序变为正常。我怎样才能避免这种情况?这里是我的code:

I am loading images directly from mp3's and displaying them along with song title in my app. To smoothen the process I am using an AsyncTask and loading the images in background. If i scroll slowly the images appear in correct order with song. However , if I scroll up and down fast , then the images jumble up for 2-3 seconds (as in appear in an incorrect order). After 2-3 seconds the order again becomes normal. How can I avoid this ? Here is my code :

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

推荐答案

Hack_on是正确的。其中的Andorid工程师在博客中讨论了博斯特这个问题:

Hack_on is correct. One of the Andorid engineers discusses this problem in a blog bost:

不过,具体的ListView行为揭示了一个问题我们
  当前实现。事实上,内存效率的原因,
  ListView控件回收的情况时,出现用户滚动的意见。
  如果一个甩列表中,一个给定的ImageView对象将被使用的许多
  倍。每次的ImageView的正确显示时间触发
  图像下载任务,这将最终改变自己的形象。那么,
  是什么问题?与大多数并行应用程序,问题的关键是
  在排序。在我们的情况下,不能保证下载
  任务将在它们被启动的顺序完成。结果
  是,最终显示在列表中的图像可以来自
  previous项目,它只是碰巧采取更长的时间来下载。
  这不是一个问题,如果你下载的图像必将一劳永逸
  所有给定ImageViews,但让我们修复它为共同的情况下
  它们在列表中使用。

However, a ListView-specific behavior reveals a problem with our current implementation. Indeed, for memory efficiency reasons, ListView recycles the views that are displayed when the user scrolls. If one flings the list, a given ImageView object will be used many times. Each time it is displayed the ImageView correctly triggers an image download task, which will eventually change its image. So where is the problem? As with most parallel applications, the key issue is in the ordering. In our case, there's no guarantee that the download tasks will finish in the order in which they were started. The result is that the image finally displayed in the list may come from a previous item, which simply happened to have taken longer to download. This is not an issue if the images you download are bound once and for all to given ImageViews, but let's fix it for the common case where they are used in a list.

这里的链接,在那里他还提供了一个解决方案:

Here's the link, where he also offers a solution:

http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

这篇关于图片使用AsyncTask的ListView中混杂了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆