LoaderManager com múltiplos carregadores: como obter o cursorloader correto

116

Para mim não está claro como obter o cursor correto se você tiver vários carregadores. Digamos que você defina dois carregadores diferentes com:

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

então em onCreateLoader () você faz coisas diferentes dependendo do 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;
} 

Por enquanto, tudo bem. Mas como colocar o cursor certo em onLoadFinished () porque você não obtém nenhum id para identificar o Cursor certo para o Cursoradapter certo.

@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 estou errado e esta é a maneira errada de obter resultados para dois adaptadores de cursor diferentes em um fragmento.

Kay Gladen
fonte
Esta é uma pergunta muito boa! É bem solicitado e aborda um assunto bastante matizado. Muito específico.
Kurtis Nusbaum
7
Deve ser mencionado que você tem de usar classes de manipulador separadas sempre que o tipo de carregador de retorno não é o mesmo em todos os carregadores, uma vez que devido ao tipo genérico apagamento, Java não permite que você para implementar uma interface ( LoaderCallbacksneste caso) com mais de um tipo. Isso simplesmente funciona no seu caso, pois nas duas vezes o resultado é a Cursor.
Matthias
1
@Matthias Ótimo, você mencionou isso! Estou apenas pensando em como ter 2 carregadores com tipos de retorno diferentes. E daí se 2 carregadores com 2 tipos de retorno diferentes? Faça uma tarefa com 1 carregador e outra com thread?
Robert
@Robert Não há necessidade de usar thread. Você pode usar dois Loaders. Acesse stackoverflow.com/a/20839825/2818583
AnV

Respostas:

119

A classe Loader possui um método chamado getId () . Espero que isso retorne o id que você associou ao carregador.

Kurtis Nusbaum
fonte
Obrigado, Kurtis! Legal! Vou tentar, mas espero que funcione. Tive a mesma ideia, mas não olhei para o objeto carregador. Em vez disso, dê uma olhada no objeto cursor ...
Kay Gladen
Funciona com Loader.getID ()! Eu verifiquei isso duas vezes agora. Ótimo!
Kay Gladen,
2
Estou pensando em fazer isso usando classes internas / anônimas, de modo que cada carregador tenha seu próprio objeto obtendo os retornos de chamada.
Jords de
@KurtisNusbaum, por que isso seria incorreto? A classe interna seria destruída junto com a Activity externa, então isso não deveria resultar em um vazamento de memória nem nada. Uma classe estática com uma referência forte à Activity é semanticamente equivalente a uma classe interna (que mantém uma referência forte implícita à classe externa).
Matthias
6
@Jords É tecnicamente correto. Eu não estou debatendo isso. Mas por que fazer tudo isso rigamarole quando você pode simplesmente ligar getId()?
Kurtis Nusbaum
32

Use o método getId () do 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
fonte
8

Se seus carregadores não têm nada em comum, exceto o tipo de classe do resultado (aqui Cursor:), é melhor você criar duas LoaderCallbacksinstâncias separadas (simplesmente como duas classes internas em sua Atividade / Fragmento), cada uma dedicada a um tratamento de carregador, em vez do que tentar misturar maçãs com laranjas.

No seu caso, parece que a fonte de dados e o tratamento do resultado são diferentes, o que requer que você escreva o código clichê extra para identificar o cenário atual e despachá-lo para o bloco de código apropriado.

BladeCoder
fonte
Eu tenho uma pergunta. O objetivo de Activityimplementar LoaderCallbackse passar thispara getLoaderManager().initLoader()é garantir que LoaderManageratue como canal de comunicação entre Activitye Loadervia LoaderCallbacks. Como esse canal de comunicação está sendo criado aqui, já que Activitynão está implementando, LoaderCallbacksmas sim criando classes internas anônimas?
ANV
3
O canal de comunicação é o LoaderCallbacks. Nada requer o uso do Activitypróprio como LoaderCallbacks. É mais simples criar vários canais de comunicação quando você precisar deles.
BladeCoder