116

To me it's not clear how to get the right cursor if you have multiple Loaders. Lets say you define two different Loader with:

getLoaderManager().initLoader(0,null,this);
getLoaderManager().initLoader(1,null,this);

then in onCreateLoader() you do different things depending on the id:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {

    if (id==0){
               CursorLoader loader = new CursorLoader(getActivity(),
            MaterialContentProvider.CONTENT_URI,null,null,null,null);
    }else{
               CursorLoader loader = new CursorLoader(getActivity(),
            CustomerContentProvider.CONTENT_URI,null,null,null,null);
            };
    return loader;
} 

so far so good. But how to get the right cursor in onLoadFinished() because you don't get any id to identify the right Cursor for the right Cursoradapter.

@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {


    mycursoradapter1.swapCursor(cursor);
    if(isResumed()){
        setListShown(true);
    }else {
        setListShownNoAnimation(true);
    }



}
//and where to get the cursor for mycursoradapter2

or am I wrong and this is the wrong way to get results for two different cursoradapter in one fragment.

Alex Lockwood
  • 81,274
  • 37
  • 197
  • 245
Kay Gladen
  • 1,730
  • 2
  • 14
  • 13
  • This is a really good question! It's well asked, and touches on a fairly nuanced subject. Very specific. – Kurtis Nusbaum Oct 31 '11 at 17:48
  • 7
    It should be mentioned that you *have* to use separate handler classes whenever the loader return type is not the same across all loaders, since due to generic type erasure, Java does not allow you to implement an interface (`LoaderCallbacks` in this case) with more than one type. It merely works in your case since both times, the result is a `Cursor`. – Matthias Dec 10 '12 at 11:49
  • 1
    @Matthias Great you'd mentioned it! I'm just considering how to have 2 loaders with different return type. So what if 2 loaders with 2 different return type? Do one task with 1 loader, another with thread instead? – Robert Jul 17 '13 at 01:57
  • @Robert No need to use thread. You may use two `Loader`s. Please go through this http://stackoverflow.com/a/20839825/2818583 – AnV Aug 28 '16 at 14:27

3 Answers3

120

The Loader class has a method called getId(). I would hope this returns the id you've associated with the loader.

Kurtis Nusbaum
  • 28,683
  • 10
  • 69
  • 97
  • Thanks, Kurtis! Cool! I'll try it but expect that it'll work. I have had the same idea but didn't look at the loader object. Have had a look at the cursor object instead... – Kay Gladen Oct 31 '11 at 17:49
  • It works with Loader.getID()! I've doublechecked this right now. Great! – Kay Gladen Oct 31 '11 at 20:20
  • 2
    I'm thinking of doing this by using inner/anonymous classes, so that each loader has it's own object getting the callbacks. – Jords Jan 26 '12 at 22:56
  • @KurtisNusbaum, why would that be incorrect? The inner class would get destroyed along with the outer Activity, so this shouldn't result in a memory leak or anything. A static class with a strong reference to the Activity is semantically equivalent to an inner class (which keeps an implicit strong reference to the outer class.) – Matthias Dec 10 '12 at 11:51
  • 6
    @Jords It's technically correct. I'm not debating that. But why do all that rigamarole when you can just call `getId()`? – Kurtis Nusbaum Dec 12 '12 at 01:20
32

Use the getId() method of Loader:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    switch (loader.getId()) {
        case 0:
            // do some stuff here
            break;
        case 1:
            // do some other stuff here
            break;
        case 2:
            // do some more stuff here
            break;
        default:
            break;
    }
}    
IgorGanapolsky
  • 23,124
  • 17
  • 109
  • 132
8

If your loaders have nothing in common but the class type of the result (here: Cursor), you're better off creating two separate LoaderCallbacks instances (simply as two inner classes in your Activity/Fragment), each one dedicated to one loader treatment, rather than trying to mix apples with oranges.

In your case it seems that both the data source and the result treatment are different, which requires you to write the extra boilerplate code to identify the current scenario and dispatch it to the appropriate code block.

BladeCoder
  • 11,697
  • 2
  • 51
  • 46
  • I have one question. The purpose of `Activity` implementing `LoaderCallbacks` and passing `this` to `getLoaderManager().initLoader()` is to ensure that `LoaderManager` acts as communication channel between `Activity` and `Loader` via `LoaderCallbacks`. How is that communication channel being created here as `Activity` isn't implementing `LoaderCallbacks` but rather creating anonymous inner classes? – AnV Aug 28 '16 at 13:58
  • 3
    The communication channel is the `LoaderCallbacks`. Nothing requires to use the `Activity` itself as `LoaderCallbacks`. It's simpler to create multiple communication channels when you need them. – BladeCoder Aug 28 '16 at 16:15