Search code examples
androidandroid-listviewandroid-sqliteandroid-cursorandroid-cursorloader

Android ListView: how to avoid database query in bindView()? Need to fetch one to many relationship data


I have a list view to display albums. In each album list item, I need to display some information from each photo in this album. Here is how my cursor loader looks like:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(this, AlbumsColumns.CONTENT_URI, null, null, null, null);
}

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

    long albumId = cursor.getLong(cursor.getColumnIndex(AlbumsColumns._ID));

    Cursor photoCursor = getContentResolver().query(PhotosColumns.CONTENT_URI, null, PhotosColumns.ALBUM_ID + " = ?", 
            new String[]{Long.toString(albumId)}, null);

    if (photoCursor.moveToFirst()){
        do{

            // Here I collect the information from each photo in the album

        }while(photoCursor.moveToNext());
    }

    photoCursor.close();
}

Basically, I let the cursor loader manage the album query, and each time in the bindView I query the photos from the passed in album cursor. I feel this can be a performance issue. Is there a better way doing this?


Solution

  • Just got an idea: use another cursor loader inside the list item. So this will be like two level cursor loader. I'll post my results later.

    Edit:

    The proposed idea should be the right way handling the issue. So my code is refactored like this:

    // In the list view activity:
    
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
    
            AlbumListItem albumListItem = (AlbumListItem)view;
    
            albumListItem.prepareView(getLoaderManager(), cursor);
        }
    
    // AlbumListItem is a class that has a cursor loader to query photos:
    public class AlbumListItem extends RelativeLayout implements LoaderManager.LoaderCallbacks<Cursor>{
    
    
    public void prepareView(LoaderManager loaderManager, Cursor albumCursor){
    
        albumId = albumCursor.getLong(albumCursor.getColumnIndex(AlbumsColumns._ID));
        // Other init stuff
    
        loaderManager.initLoader(UNIQUE_LOADER_ID, null, this);
    }
    
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    
        // Here is the async query part.
    
        return new CursorLoader(context, PhotosColumns.CONTENT_URI, null, PhotosColumns.ALBUM_ID + " = ?", new String[]{Long.toString(albumId)}, null);
    }
    
    }