AsyncTask未在ListView中的正确行中设置正确的图像

时间:2014-05-09 17:51:13

标签: android listview android-listview android-asynctask imageview

我正在尝试制作专辑ListView。在那里我使用AsyncTask将album_art图像加载到列表缩略图。一切都很好,但问题是那些图像没有附加正确的行。如果我滚动列表视图,相册图像会随机变化。有时同一图像显示在多行中,有时根本没有图像。我不知道为什么会这样。它看起来像一种线程问题。我该如何解决?

这是我的代码:

public class PropertyOfAlbum extends BaseAdapter {


    public static ViewHolder holder;
    private Context mContext;
    Cursor cursor;
    private FakeImageLoader mFakeImageLoader;
    private LayoutInflater layoutInflater;
    Typeface tf, tf2, tf3;
    Bitmap coverBitmap;
    //private FakeImageLoader mFakeImageLoader;

    public PropertyOfAlbum(Context context, Cursor cur) {
        super();
        mContext = context;
        cursor = cur;
        tf = Typeface.createFromAsset(context.getAssets(),
                "fonts/gang_wolfik_blade.ttf");
        tf2 = Typeface.createFromAsset(context.getAssets(),
                "fonts/gang_wolfik_blade.ttf");
        tf3 = Typeface.createFromAsset(context.getAssets(),
                "fonts/gang_wolfik_blade.ttf");
        layoutInflater = LayoutInflater.from(context);
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @SuppressLint("NewApi")
    public View getView(final int position, View view, ViewGroup parent) {
        cursor.moveToPosition(position);
        // Using an AsyncTask to load the slow images in a background thread

        if (view == null) {
            view = layoutInflater.inflate(R.layout.album_row, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.title);
            holder.duration = (TextView) view.findViewById(R.id.duration);
            holder.artist = (TextView) view.findViewById(R.id.artist);
            holder.iv = (ImageView) view.findViewById(R.id.list_image);
            holder.col = cursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM_ART);

            view.setTag(holder);        
        }else{
            holder = (ViewHolder) view.getTag();
        }
        //mFakeImageLoader = new FakeImageLoader(cursor,holder.col);
        holder.title.setTypeface(tf);
        holder.artist.setTypeface(tf2);
        holder.duration.setTypeface(tf3);
        holder.title.setTextSize(18);
        Log.d(null, "col " + holder.col);

        holder.title.setText(cursor.getString(1));
        holder.artist.setText(cursor.getString(2));
        holder.duration.setText(cursor.getString(4));
        //coverBitmap = BitmapFactory.decodeFile(cursor.getString(holder.col));
        if(coverBitmap == null){
            holder.iv.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album));
        }else{
            holder.iv.setImageBitmap(coverBitmap);
        }
        holder.position = position;
        new AsyncTask<ViewHolder, Void, Bitmap>() {
            private ViewHolder v;

            @Override
            protected Bitmap doInBackground(ViewHolder... params) {
                v = params[0];
                coverBitmap = BitmapFactory.decodeFile(cursor.getString(holder.col));
                return coverBitmap;
            }

            @Override
            protected void onPostExecute(Bitmap result) {
                super.onPostExecute(result);
                if(v.position == position){
                    if (coverBitmap==null) {
                        holder.iv.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album));
                    }else{
                        holder.iv.setImageBitmap(coverBitmap);
                    }
                }
            }
        }.execute(holder);
        return view;

    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return cursor.getCount();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    public static class ViewHolder {
        TextView title;
        TextView duration;
        TextView artist;
        ImageView iv;
        int col,position;
    }

}

2 个答案:

答案 0 :(得分:1)

将AsyncTask实例与适配器上的View行链接起来并不是一个好习惯,通常,在必要时将它放在另一个流中的getView()之外,因为getView上的视图( )在AsyncTask加载完成时,您将无法控制该视图上显示的内容。

我能给你的最好建议是忘记这种方法并将毕加索应用于你的项目。 Picasso是Android上最简单但功能最强大的图片加载库,我保证你不会后悔:http://square.github.io/picasso/

答案 1 :(得分:0)

您只有1个对coverBitmap的引用。每次调用getView()时(例如每次滚动),它都会重用一些视图(即convertView!= null),你将新的背景设置为当前的任何coverBitmap,并且然后启动一个新的AsyncTask,然后再次替换coverBitmap。因此,循环继续,您遇到了问题。

现在,一个解决方案是让某种对象将位图映射到您引用的特定相册。

EG。

private Map<String, Bitmap> albumImages = new HashMap<String, Bitmap>();

既然你有东西可以存放你的东西,你可以删除你的&#34; coverBitmap&#34;并将您的位图添加到AsyncTask中的albumImages:

        @Override
        protected Bitmap doInBackground(ViewHolder... params) {
            v = params[0];
            return BitmapFactory.decodeFile(cursor.getString(holder.col));
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);

            // Add the returned Bitmap to our Map if it's not null
            if(result != null)  alumbImages.put(cursor.getString(holder.col), result);

            if(v.position == position){
                if (result == null) {
                    holder.iv.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album));
                }else{
                    holder.iv.setImageBitmap(result);
                }
            }
        }

现在让我们回到你的getView()方法并替换你获取和设置图像的方式,并确保每次调用该方法时都不会触发AsyncTask:

    Bitmap albumImage = albumImages.get(cursor.getString(holder.col));
    if(albumImage == null){
        holder.iv.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album));

         // Now is where you can call the AsyncTask, so that it's only called if we don't already have the image:
          new AsyncTask<ViewHolder, Void, Bitmap>() { ... }
    }
    else holder.iv.setImageBitmap(albumImage); 
    holder.position = position;

然而,这仍然远非最佳,我建议使用延迟加载库,以便更好地处理保留大量图像所需的所有资源。这个用户非常友好:https://github.com/nostra13/Android-Universal-Image-Loader