LoaderManager with multiple loaders: how to get the right cursorloader
Asked Answered
P

3

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.

Protoxylem answered 31/10, 2011 at 17:39 Comment(4)
This is a really good question! It's well asked, and touches on a fairly nuanced subject. Very specific.Rotberg
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.Rosel
@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?Univocal
@Univocal No need to use thread. You may use two Loaders. Please go through this https://mcmap.net/q/189496/-multiple-loaders-in-same-activityBlankbook
R
121

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

Rotberg answered 31/10, 2011 at 17:45 Comment(5)
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...Protoxylem
It works with Loader.getID()! I've doublechecked this right now. Great!Protoxylem
I'm thinking of doing this by using inner/anonymous classes, so that each loader has it's own object getting the callbacks.Kaiser
@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.)Rosel
@Kaiser It's technically correct. I'm not debating that. But why do all that rigamarole when you can just call getId()?Rotberg
A
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;
    }
}    
Almuce answered 23/1, 2014 at 19:39 Comment(0)
S
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.

Scholem answered 20/4, 2014 at 0:54 Comment(2)
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?Blankbook
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.Scholem

© 2022 - 2024 — McMap. All rights reserved.