LoaderManager mit mehreren Loadern: So erhalten Sie den richtigen Cursorloader

116

Für mich ist nicht klar, wie man den richtigen Cursor bekommt, wenn man mehrere Lader hat. Nehmen wir an, Sie definieren zwei verschiedene Loader mit:

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

dann machen Sie in onCreateLoader () abhängig von der ID verschiedene Dinge:

@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 weit, ist es gut. Aber wie man den richtigen Cursor in onLoadFinished () erhält, weil man keine ID erhält, um den richtigen Cursor für den richtigen Cursoradapter zu identifizieren.

@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

oder irre ich mich und dies ist der falsche Weg, um Ergebnisse für zwei verschiedene Cursoradapter in einem Fragment zu erhalten.

Kay Gladen
quelle
Das ist eine wirklich gute Frage! Es ist gut gefragt und berührt ein ziemlich nuanciertes Thema. Sehr spezifisch.
Kurtis Nusbaum
7
Es sollte erwähnt werden , dass Sie haben getrennte Handler - Klassen zu verwenden , wenn der Lader Rückgabetyp nicht das gleiche für alle Lader ist, da aufgrund generischer Typ Löschung, Java ermöglicht es Ihnen nicht eine Schnittstelle (implementieren LoaderCallbacksin diesem Fall) mit mehr als einem Art. Es funktioniert nur in Ihrem Fall, da beide Male das Ergebnis a ist Cursor.
Matthias
1
@ Matthias Großartig, dass du es erwähnt hast! Ich überlege nur, wie ich 2 Lader mit unterschiedlichem Rückgabetyp haben soll. Was ist, wenn 2 Lader mit 2 verschiedenen Rückgabetypen? Führen Sie stattdessen eine Aufgabe mit 1 Lader und eine andere mit Thread aus?
Robert
@ Robert Keine Notwendigkeit, Thread zu verwenden. Sie können zwei Loaders verwenden. Bitte gehen Sie durch diese stackoverflow.com/a/20839825/2818583
AnV

Antworten:

119

Die Loader-Klasse verfügt über eine Methode namens getId () . Ich würde hoffen, dass dies die ID zurückgibt, die Sie dem Loader zugeordnet haben.

Kurtis Nusbaum
quelle
Danke, Kurtis! Cool! Ich werde es versuchen, aber erwarten, dass es funktionieren wird. Ich hatte die gleiche Idee, habe mir aber das Ladeobjekt nicht angesehen. Habe mir stattdessen das Cursor-Objekt angesehen ...
Kay Gladen
Es funktioniert mit Loader.getID ()! Ich habe das jetzt doppelt überprüft. Toll!
Kay Gladen
2
Ich denke darüber nach, innere / anonyme Klassen zu verwenden, damit jeder Loader sein eigenes Objekt hat, das die Rückrufe erhält.
Jords
@ KurtisNusbaum, warum sollte das falsch sein? Die innere Klasse würde zusammen mit der äußeren Aktivität zerstört werden, daher sollte dies nicht zu einem Speicherverlust oder Ähnlichem führen. Eine statische Klasse mit einem starken Bezug zur Aktivität ist semantisch äquivalent zu einer inneren Klasse (die einen implizit starken Bezug zur äußeren Klasse
Matthias
6
@Jords Es ist technisch korrekt. Ich diskutiere das nicht. Aber warum all diese Rigamarole, wenn Sie einfach anrufen können getId()?
Kurtis Nusbaum
32

Verwenden Sie die getId () -Methode von 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
quelle
8

Wenn Ihre Loader nichts gemeinsam haben als den Klassentyp des Ergebnisses (hier :) Cursor, sollten Sie besser zwei separate LoaderCallbacksInstanzen erstellen (einfach als zwei innere Klassen in Ihrer Aktivität / Ihrem Fragment), die jeweils einer Loader-Behandlung gewidmet sind als zu versuchen, Äpfel mit Orangen zu mischen.

In Ihrem Fall scheinen sowohl die Datenquelle als auch die Ergebnisbehandlung unterschiedlich zu sein. Daher müssen Sie den zusätzlichen Boilerplate-Code schreiben, um das aktuelle Szenario zu identifizieren und an den entsprechenden Codeblock zu senden.

BladeCoder
quelle
Ich habe eine Frage. Der Zweck der ActivityUmsetzung LoaderCallbacksund Weitergabe thisan getLoaderManager().initLoader()ist , um sicherzustellen , dass LoaderManagerwirkt als Kommunikationskanal zwischen Activityund Loaderüber LoaderCallbacks. Wie wird dieser Kommunikationskanal hier erstellt, da er Activitynicht implementiert LoaderCallbacks, sondern anonyme innere Klassen erstellt?
AnV
3
Der Kommunikationskanal ist der LoaderCallbacks. Nichts erfordert, sich Activityselbst als zu verwenden LoaderCallbacks. Es ist einfacher, bei Bedarf mehrere Kommunikationskanäle zu erstellen.
BladeCoder