11

I need to make a ListAdapter that presents data from multiple ContentProviders. The ContentProviders themselves represent one table each from relational database.

I want to use the CursorLoader system to retrieve aggregate data into ListView. Is this possible to do with 1 loader or do I need to use multiple loaders? I'd prefer to use one.

I'm not sure how I can have 2 ContentProviders interact with each other beyond doing the join manually in code which doesn't seem like a great option either.

Jeremy Edwards
  • 14,620
  • 17
  • 74
  • 99

3 Answers3

12

You will have to write a Custom Loader class. For example:

public class FooLoader extends AsyncTaskLoader {

    Context context;

    public FooLoader(Context context) {
        super(context);
        this.context = context;
    }

    @Override
    public Cursor loadInBackground() {
        Log.d(TAG, "loadInBackground");
        YourDatabase dbHelper = new YourDataBase(context);
        SQLiteDatabase db= dbHelper.getReadableDatabase();

        /*** create a custom cursor whether it is join of multiple tables or complex query**/
        Cursor cursor = db.query(<TableName>, null,null, null, null, null, null, null);
        return cursor; 
    }
}

In the calling activity or fragments onCreate() method, you would need to call the custom loader class:

public class MyFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate():" + mContent);
        Loader loader = getLoaderManager().initLoader(0, null, this);
        loader.forceLoad();
    }   

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        Log.d(TAG, "onCreateLoader()")  ;
        return new FooLoader(getActivity());
    }

    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        Log.d(TAG, "onLoadFinished");            
    }

    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {   
    }
}
Joshua Dwire
  • 5,415
  • 5
  • 29
  • 50
rOrlig
  • 2,489
  • 4
  • 35
  • 48
  • Sorry but "multiple ContentProviders" is not the same as "multiple tables in my app's db". The ContentProviders might be from different apps in which case your solution is not a solution. (Necroposting, but maybe somebody has a hint) – Giszmo Sep 23 '16 at 03:07
1

You might want to take a look at CursorJoiner.

Gábor
  • 9,466
  • 3
  • 65
  • 79
0

I'm new to ContentLoaders myself, but I haven't yet seen a way that you could use one ContentLoader to handle multiple ContentProviders.

Are the tables you're querying in separate databases? It isn't clear from your question. If the tables are all in the same database, one alternative might be to instead use one ContentProvider for the separate tables. The data can be joined and returned to one cursor, which means you could use one CursorLoader. The SQLiteQueryBuilder.setTables() method has some information on this:

http://developer.android.com/reference/android/database/sqlite/SQLiteQueryBuilder.html#setTables%28java.lang.String%29

and you can see it in action here:

http://code.google.com/p/openintents/source/browse/trunk/shoppinglist/ShoppingList/src/org/openintents/shopping/provider/ShoppingProvider.java

this might also be helpful: https://stackoverflow.com/a/3196484/399105

Community
  • 1
  • 1
bmaupin
  • 14,427
  • 5
  • 89
  • 94