Search code examples
androidandroid-asynctaskandroid-cursoradapter

How to load albumArt using AsyncTask in cursor adapter


I have a problem with retrieving albumArt and setting that art to ImageView using AsyncTask in cursor adapter. When I open my app it looks like this: enter image description here

Then I scroll down the list and everything is fine(but also if I scroll list not very fast): enter image description here

Then I scroll list back to the very beggining(not fast) and it looks fine as well: enter image description here

Probably I do something wrong, I think, so I have question:

Is it possible somehow to solve that problem, I already tried a lot of different ways on how to implement AsyncTask and make it works fine, but in the end of the day it looks always the same.

Below is code for cursor adapter:

public class AllSongsCursorAdapter extends CursorAdapter {

public AllSongsCursorAdapter(Context context, Cursor cursor) {
    super(context, cursor, 0);
}

public boolean isCheckBoxVisible;
private AddToFavouritesArray favouritesArray = AddToFavouritesArray.getInstance();

private static class ViewHolder {
    CheckBox checkBox;
    TextView title;
    TextView artist;
    ImageView albumArt;

    private ViewHolder(View view) {

        checkBox = (CheckBox) view.findViewById(R.id.favouritesCheckBox);
        title = (TextView) view.findViewById(R.id.title);
        artist = (TextView) view.findViewById(R.id.artist);
        albumArt = (ImageView) view.findViewById(R.id.albumArt);
    }
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
    View view = LayoutInflater.from(context).inflate(R.layout.song_item, viewGroup, false);
    ViewHolder viewHolder = new ViewHolder(view);
    view.setTag(viewHolder);
    return view;
}

@Override
public void bindView(View view, Context context, final Cursor cursor) {

    final ViewHolder viewHolder = (ViewHolder) view.getTag();
    if (isCheckBoxVisible) {
        viewHolder.checkBox.setVisibility(View.VISIBLE);
    } else {
        viewHolder.checkBox.setVisibility(View.GONE);
    }

    final int position = cursor.getPosition();
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {

            if (b) {
                favouritesArray.integerArray.add(position);

            } else {
                favouritesArray.integerArray.remove(Integer.valueOf(position));
            }
        }
    });

    int songTitle = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
    int songArtist = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);

    String currentTitle = cursor.getString(songTitle);
    String currentArtist = cursor.getString(songArtist);

    viewHolder.title.setText(currentTitle);
    viewHolder.artist.setText(currentArtist);

    //__________________________ALBUM_ART_______________________________________________________

    viewHolder.albumArt.setTag(cursor.getPosition());

    new AsyncTask<ViewHolder, Void, Bitmap>(){

        private ViewHolder viewHolder;

        @Override
        protected Bitmap doInBackground(ViewHolder... viewHolders) {
            viewHolder = viewHolders[0];
            int id = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
            long songId = cursor.getLong(id);

            Bitmap albumArt = getAlbumId(context, songId);
            return albumArt;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if(bitmap != null) {
                viewHolder.albumArt.setImageBitmap(bitmap);
            }else{
                viewHolder.albumArt.setImageResource(R.drawable.placeholder);
            }
        }
    }.execute(viewHolder);
}

private Bitmap getAlbumId(Context context, long id) {

    Bitmap albumArt = null;
    String selection = MediaStore.Audio.Media._ID + " = " + id + "";
    Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{
                    MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
            selection, null, null);
    if (cursor.moveToFirst()) {
        long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));

        albumArt = getAlbumArt(context, albumId);
    }
    cursor.close();
    return albumArt;

}

private Bitmap getAlbumArt(Context context, long albumId) {

    Bitmap albumArt = null;
    String selection = MediaStore.Audio.Albums._ID + " = " + albumId + "";
    Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, selection, null, null);

    if (cursor.moveToFirst()) {

        int art = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART);

        String currentArt = cursor.getString(art);
        albumArt = BitmapFactory.decodeFile(currentArt);
    }
    cursor.close();
    return albumArt;
}

}

And yes, sure, without AsyncTask everything works fine except scrolling is very slow. Thank you in advance!

EDIT

In the end of the day, that's how it works. Thank you very much @ Orest Savchak, my up-vote and acceptance for your answer. Thanks a lot. //__________________________ALBUM_ART_______________________________________________________

    int id = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
    long songId = cursor.getLong(id);
    String string = getAlbumArtPath(context, songId);
    if(string!=null) {
        Picasso.with(context)
                .load(new File(string))
                .into(viewHolder.albumArt);
    }else{
        viewHolder.albumArt.setImageResource(R.drawable.placeholder);
    }
}
private String getAlbumArtPath(Context context, long id) {

    String selection = MediaStore.Audio.Media._ID + " = " + id + "";
    Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{
                    MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
            selection, null, null);
    if (cursor.moveToFirst()) {
        long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));

        return getAlbumArt(context, albumId);
    }
    cursor.close();
    return null;

}

private String getAlbumArt(Context context, long albumId) {

    String selection = MediaStore.Audio.Albums._ID + " = " + albumId + "";
    Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, selection, null, null);

    if (cursor.moveToFirst()) {

        int art = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART);

        return cursor.getString(art);
    }
    cursor.close();
    return null;
}

Solution

  • You should manage your tasks by yourself. Your views are recycled, so, you have one view for different rows, it causes a problem. Most of project use some libraries, that do it automatically for you - much easier, e.g Picasso

    Picasso.with(context).load(new File(getAlbumArtPath(context, songId))).into(viewHolder.albumArt);
    
    private String getAlbumArtPath(Context context, long id) {
    
        String selection = MediaStore.Audio.Media._ID + " = " + id + "";
        Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{
                        MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
                selection, null, null);
        if (cursor.moveToFirst()) {
            long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
    
            return getAlbumArt(context, albumId);
        }
        cursor.close();
        return null;
    
    }
    
    private String getAlbumArt(Context context, long albumId) {
    
        String selection = MediaStore.Audio.Albums._ID + " = " + albumId + "";
        Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, selection, null, null);
    
        if (cursor.moveToFirst()) {
    
            int art = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART);
    
            return cursor.getString(art);
        }
        cursor.close();
        return null;
    }