GridView + CursorAdapter + AsyncTask随机加载图像

时间:2012-01-16 14:42:39

标签: android gridview android-asynctask simplecursoradapter

我使用SimpleCursorAdapter和GridActivity(我基于ListActivity编写的扩展活动)从MediaStore加载音乐专辑,并使用AsyncTask加载每个专辑封面。

我在bindViewgetView中尝试过此操作,如下所示:

new AsyncAlbumArtLoader(viewholder.album_art, mShowFadeAnimation).execute(aid, width, height);

班级AsyncAlbumArtLoader

private class AsyncAlbumArtLoader extends AsyncTask<Object, Void, Bitmap> {

    boolean enable_animation = false;
    private ImageView imageview;

    public AsyncAlbumArtLoader(ImageView imageview, Boolean animation) {

        enable_animation = animation;
        this.imageview = imageview;
    }

    @Override
    protected void onPreExecute() {

        if (enable_animation) {
            imageview.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),
                    android.R.anim.fade_out));
            imageview.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    protected Bitmap doInBackground(Object... params) {

        return MusicUtils.getCachedArtwork(getApplicationContext(), (Long) params[0],
                (Integer) params[1], (Integer) params[2]);
    }

    @Override
    protected void onPostExecute(Bitmap result) {

        if (result != null) {
            imageview.setImageBitmap(result);
        } else {
            imageview.setImageResource(R.drawable.albumart_mp_unknown_list);
        }
        if (enable_animation) {
            imageview.setVisibility(View.VISIBLE);
            imageview.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),
                    android.R.anim.fade_in));
        }

    }
}

但是图像随机地在gridview项目之间移动。

您可以看到屏幕录制视频here

已编辑通过setTag()防止此错误,并且getTag()也无效。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view = super.getView(position, convertView, parent);

        mAlbumCursor.moveToPosition(position);

        ViewHolder viewholder = (ViewHolder) view.getTag();

        String album_name = mAlbumCursor.getString(mAlbumIndex);
        if (album_name == null || MediaStore.UNKNOWN_STRING.equals(album_name)) {
            viewholder.album_name.setText(R.string.unknown_album_name);
        } else {
            viewholder.album_name.setText(album_name);
        }

        String artist_name = mAlbumCursor.getString(mArtistIndex);
        if (album_name == null || MediaStore.UNKNOWN_STRING.equals(album_name)) {
            viewholder.artist_name.setText(R.string.unknown_artist_name);
        } else {
            viewholder.artist_name.setText(artist_name);
        }

        // We don't actually need the path to the thumbnail file,
        // we just use it to see if there is album art or not
        long aid = mAlbumCursor.getLong(mAlbumIdIndex);
        int width = getResources().getDimensionPixelSize(R.dimen.gridview_bitmap_width);
        int height = getResources().getDimensionPixelSize(R.dimen.gridview_bitmap_height);

        viewholder.album_art.setTag(aid);
        new AsyncAlbumArtLoader(viewholder.album_art, mShowFadeAnimation, aid, width, height).execute();

        long currentalbumid = MusicUtils.getCurrentAlbumId();
        if (currentalbumid == aid) {
            viewholder.album_name.setCompoundDrawablesWithIntrinsicBounds(0, 0,
                    R.drawable.ic_indicator_nowplaying_small, 0);
        } else {
            viewholder.album_name.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        }

        return view;
    }


// FIXME image loaded some times incorrect
private class AsyncAlbumArtLoader extends AsyncTask<Object, Void, Bitmap> {

    boolean enable_animation = false;
    private ImageView imageview;
    private long album_id;
    private int width,height;

    public AsyncAlbumArtLoader(ImageView imageview, Boolean animation, long album_id, int width, int height) {

        enable_animation = animation;
        this.imageview = imageview;
        this.album_id = album_id;
        this.width = width;
        this.height = height;
    }

    @Override
    protected void onPreExecute() {

        if (imageview.getTag() == null || (Long)imageview.getTag() != album_id) {
            return;
        }

        if (enable_animation) {
            imageview.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),
                    android.R.anim.fade_out));
            imageview.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    protected Bitmap doInBackground(Object... params) {

        if (imageview.getTag() == null || (Long)imageview.getTag() != album_id) {
            return null;
        }

        return MusicUtils.getCachedArtwork(getApplicationContext(), album_id,
                width, height);
    }

    @Override
    protected void onPostExecute(Bitmap result) {

        if (imageview.getTag() == null || (Long)imageview.getTag() != album_id) {
            return;
        }

        if (result != null) {
            imageview.setImageBitmap(result);
        } else {
            imageview.setImageResource(R.drawable.albumart_mp_unknown_list);
        }
        if (enable_animation) {
            imageview.setVisibility(View.VISIBLE);
            imageview.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),
                    android.R.anim.fade_in));
        }

    }
}

1 个答案:

答案 0 :(得分:1)

问题是,AsyncTask不知道它们在哪个ImageView开始时,它们会重叠。

要防止这种情况,您需要执行以下操作: 在getView方法中(在调用AsyncTask-Constructor之前,你需要在ImageView中设置一个Tag:myImageView.setTag(object)。最好的选择是,如果你使用getView获取其信息的对象。在你身上case我认为它是带有Album-Information的ArrayList。让'说myImageView.setTag(myAlbumArray.get(position)) TAG必须是独一无二的 现在向AsyncTask类添加一个新的String'标记'并添加this.tag = imageview.getTag().toString() 现在最后在onPostExecute

中添加测试
 if (imageview.getTag().toString().equals(tag)) {
// you got the right imageView, *your PostExecute Code* }
else {// wrong one, do nothing
}