26

Quindi ho il mio MainDisplayActivity che implementa sia Activity e LoaderManager.LoaderCallbacks<Cursor>. Qui ho A ListView, che riempio con le informazioni Agenda che ottengo dal mio database utilizzando un ContentProvider. Ho anche un GridView che è un calendario. Ho impostato quando si fa clic su una cella, che l'agenda è aggiornata con il giorno cliccato. Il mio problema è che quando riusci il Loader che ho creato in onCreate() all'interno di setOnItemClickListener(), non aggiorna le informazioni con il nuovo cursore che sto creando. Posso solo creare un nuovo Loader con un altro ID, e funziona una volta, ma una volta che clicco su un altro giorno, si interrompe l'aggiornamento. Il problema, sta nel cursore. Come posso aggiornare un cursore da un Loader in modo da non dover continuare a creare un nuovo Loader? Grazie in anticipo!Come posso aggiornare il cursore da un CursorLoader?

chiamata iniziale per creare la Loader onCreate() nel mio MainDisplayActivity classe:

makeProviderBundle(new String[] {"_id, event_name, start_date, start_time, end_date, end_time, location"}, 
      "date(?) >= start_date and date(?) <= end_date", new String[]{getChosenDate(), getChosenDate()}, null); 
    getLoaderManager().initLoader(0, myBundle, MainDisplayActivity.this); 

    list.setAdapter(agendaAdapter); 

Questi sono i metodi modificate da LoaderCallbacks<Cursor>

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    Uri baseUri = SmartCalProvider.CONTENT_URI; 
    return new CursorLoader(this, baseUri, args.getStringArray("projection"), 
      args.getString("selection"), args.getStringArray("selectionArgs"), args.getBoolean("sortOrder") ? args.getString("sortOrder") : null); 
} 



@Override 
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { 
    agendaAdapter.swapCursor(arg1); 
} 



@Override 
public void onLoaderReset(Loader<Cursor> arg0) { 
    //Not really sure how this works. Maybe I need to fix this here? 
    agendaAdapter.swapCursor(null); 

} 

public void makeProviderBundle(String[] projection, String selection, String[] selectionArgs, String sortOrder){ 
    /*this is a convenience method to pass it arguments 
    * to pass into myBundle which in turn is passed 
    * into the Cursor loader to query the smartcal.db*/ 
    myBundle = new Bundle(); 
    myBundle.putStringArray("projection", projection); 
    myBundle.putString("selection", selection); 
    myBundle.putStringArray("selectionArgs", selectionArgs); 
    if(sortOrder != null) myBundle.putString("sortOrder", sortOrder); 
} 

Qualsiasi codice aggiuntivo necessario, non esitate a chiedere . Grazie ancora per qualsiasi aiuto!

+0

È stata la mia esperienza che quando si utilizza il 'ContentResolver' per aggiornare un contenuto in un' ContentProvider' che il 'cursore' viene notificato e l'elenco si aggiorna automaticamente. Potresti pubblicare anche il tuo codice onClick? – stuckless

+0

Lo so bene. Ho assunto questo anche perché tutti dicevano quanto fosse comodo. Ma non lo fa. Il problema è che capisco anche come questo non possa funzionare. Quando il 'Loader' viene creato per la prima volta, chiama' onCreateLoader() '. Quando si chiama 'getLoaderManager(). InitLoader()', se il primo argomento, l'ID è uguale a un 'Loader' precedentemente istanziato,' onCreateLoader() 'probabilmente non verrà chiamato. Naturalmente questa è pura speculazione da parte mia, mentre sto ancora imparando, ma ho pensato che dovesse esserci un metodo per caricare un nuovo Cursore, se così fosse. Alex è stato abbastanza gentile da fornirlo! – Andy

risposta

40

Hai solo bisogno di spostare il codice un po 'e chiamare restartLoader. Cioè,

  1. Quando l'utente fa clic su un elemento della lista, si modifica in qualche modo la variabile di istanza privata che viene restituito in getChosenDate() (mi viene volutamente vaga qui perché non è stato specificato che cosa esattamente getChosenDate() rendimenti).

  2. Una volta effettuata la modifica, chiamare getLoaderManager().restartLoader() sul numero Loader. I tuoi vecchi dati saranno scartati e restartLoader attiverà onCreateLoader per essere chiamato di nuovo. Questa volta, getChosenDate() restituirà un valore diverso (a seconda dell'elemento della lista su cui è stato fatto clic) e dovrebbe farlo. Il tuo onCreateLoader attuazione dovrebbe essere simile a questa:

    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
        Uri baseUri = SmartCalProvider.CONTENT_URI; 
    
        makeProviderBundle(
         new String[] { "_id, event_name, start_date, start_time, end_date, end_time, location" }, 
         "date(?) >= start_date and date(?) <= end_date", 
         new String[]{ getChosenDate(), getChosenDate() }, 
         null); 
    
        return new CursorLoader(
          this, 
          baseUri, 
          args.getStringArray("projection"), 
          args.getString("selection"), 
          args.getStringArray("selectionArgs"),  
          args.getBoolean("sortOrder") ? args.getString("sortOrder") : null); 
    } 
    

Fammi sapere se questo ha un senso. :)

+0

Santo shiznit lol. Questo è genio haha. Vedo quello che stai dicendo. Quindi il metodo che potrei chiamare è 'restartLoader()'. Come mai non vedo quel metodo in CursorLoader ?! Oh e scusa, 'getChosenDate()' restituisce una data di stringa nel formato usato da Database, quindi posso fare tutto il filtraggio con SQLite piuttosto che con codice java. – Andy

+0

Amico !!! Ti amo! Ha funzionato magnificamente. E guardando il mio codice mi sono reso conto di 'myBundle.putString (" date ", getChosenDate());', non era necessario. Quindi l'ho tolto. Lo userò solo quando chiami 'makeProviderBundle()'. Grazie mille ... ANCORA! – Andy

+11

Haha ... sei facilmente eccitabile, vero? Sono contento di poter aiutare :). –