Question

I use SimpleCursorAdapter and GridActivity (extended Activity written by me based on ListActivity) to load music albums from MediaStore, and use AsyncTask load each album art .

I tried this in bindView or getView, like this:

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

class 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));
        }

    }
}

But images shifting between gridview items randomly.

You can see screen record video here.

edited prevent this error by setTag() and getTag() is also no effect.

    @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));
        }

    }
}
Was it helpful?

Solution

The Problem is, that the AsyncTask don't know für which ImageView they where started, respectivley they overlap.

To prevent this you need to do the following: In your getView Method (before calling the AsyncTask-Constructor you need so set a Tag to your ImageView: myImageView.setTag(object). The best choice is, if you use the object from which getView gets its information. In you case i think it is the ArrayList with the Album-Information. Let' say myImageView.setTag(myAlbumArray.get(position)) THE TAG MUST BE UNIQUE
Now add a new String 'tag' to your AsyncTask class and add this.tag = imageview.getTag().toString().
Now finally add the test in your onPostExecute:

 if (imageview.getTag().toString().equals(tag)) {
// you got the right imageView, *your PostExecute Code* }
else {// wrong one, do nothing
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top