LoaderManager avec plusieurs chargeurs: comment obtenir le bon curseur de chargement

116

Pour moi, il n'est pas clair comment obtenir le bon curseur si vous avez plusieurs chargeurs. Disons que vous définissez deux chargeurs différents avec:

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

puis dans onCreateLoader () vous faites différentes choses en fonction de l'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;
} 

jusqu'ici tout va bien. Mais comment obtenir le bon curseur dans onLoadFinished () car vous n'obtenez aucun identifiant pour identifier le bon curseur pour le bon 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

ou je me trompe et c'est la mauvaise façon d'obtenir des résultats pour deux curseurs différents dans un fragment.

Kay Gladen
la source
C'est une très bonne question! C'est bien posé, et touche à un sujet assez nuancé. Très spécifique.
Kurtis Nusbaum
7
Il convient de mentionner que vous devez utiliser des classes de gestionnaire distinctes chaque fois que le type de retour du chargeur n'est pas le même sur tous les chargeurs, car en raison de l'effacement de type générique, Java ne vous permet pas d'implémenter une interface ( LoaderCallbacksdans ce cas) avec plus d'un type. Cela fonctionne simplement dans votre cas puisque les deux fois, le résultat est un fichier Cursor.
Matthias
1
@Matthias Great vous l'avez mentionné! J'envisage juste comment avoir 2 chargeurs avec un type de retour différent. Et si 2 chargeurs avec 2 types de retour différents? Faire une tâche avec 1 chargeur, une autre avec thread à la place?
Robert
@Robert Pas besoin d'utiliser le fil. Vous pouvez utiliser deux Loaders. Veuillez parcourir ce stackoverflow.com/a/20839825/2818583
AnV

Réponses:

119

La classe Loader a une méthode appelée getId () . J'espère que cela renvoie l'identifiant que vous avez associé au chargeur.

Kurtis Nusbaum
la source
Merci, Kurtis! Cool! Je vais l'essayer mais je m'attends à ce que ça marche. J'ai eu la même idée mais je n'ai pas regardé l'objet chargeur. J'ai jeté un œil à l'objet curseur à la place ...
Kay Gladen
Cela fonctionne avec Loader.getID ()! J'ai revérifié cela maintenant. Génial!
Kay Gladen
2
Je pense faire cela en utilisant des classes internes / anonymes, de sorte que chaque chargeur ait son propre objet recevant les rappels.
Jords
@KurtisNusbaum, pourquoi est-ce incorrect? La classe interne serait détruite avec l'activité externe, donc cela ne devrait pas entraîner de fuite de mémoire ou quoi que ce soit. Une classe statique avec une référence forte à l'activité est sémantiquement équivalente à une classe interne (qui conserve une référence forte implicite à la classe externe.)
Matthias
6
@Jords C'est techniquement correct. Je ne discute pas de ça. Mais pourquoi tout ce rigamarole alors que vous pouvez simplement appeler getId()?
Kurtis Nusbaum
32

Utilisez la méthode getId () de 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
la source
8

Si vos chargeurs n'ont rien en commun à part le type de classe du résultat (ici :) Cursor, vous feriez mieux de créer deux LoaderCallbacksinstances distinctes (simplement comme deux classes internes dans votre Activité / Fragment), chacune dédiée à un traitement de chargeur, plutôt que d'essayer de mélanger des pommes avec des oranges.

Dans votre cas, il semble que la source de données et le traitement des résultats soient différents, ce qui vous oblige à écrire le code standard supplémentaire pour identifier le scénario actuel et l'envoyer au bloc de code approprié.

BladeCoder
la source
J'ai une question. Le but de la Activitymise en œuvre LoaderCallbackset passant thisà getLoaderManager().initLoader()faire en sorte que LoaderManageragit en tant que canal de communication entre Activityet Loaderpar l' intermédiaire LoaderCallbacks. Comment ce canal de communication est-il créé ici Activitysans implémenter LoaderCallbacksmais plutôt créer des classes internes anonymes?
AnV
3
Le canal de communication est le LoaderCallbacks. Rien ne nécessite d'utiliser le Activitylui - même comme LoaderCallbacks. Il est plus simple de créer plusieurs canaux de communication lorsque vous en avez besoin.
BladeCoder