2012-06-08 5 views
6

Ho un cursore restituito su un callback onLoadFinished (da LoaderManager.LoaderCallbacks) e desidero eseguire qualche (eventualmente costoso) post-elaborazione su questo cursore. Quindi, sto sparando un AsyncTask che usa questo cursore. Tuttavia, mi sto crash intermittenti con questa eccezione:Utilizzo di un cursore restituito da un LoaderManager in un AsyncTask

android.database.StaleDataException: Attempted to access a cursor after it has been closed. 

Il mio sospetto è che questo sta accadendo perché il cursore (gestito dal programma di caricamento nel thread UI) viene chiuso prima che il thread in background è rifinito con esso, poiché questo è un cursore gestito. Ecco del codice Parafrasato:

private class LoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 
    @Override 
    public void onCreateLoader(int d, Bundle args) { 
     return new CursorLoader(context, uri, projection, selection, selectionArgs, sortOrder); 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
     processCursor(cursor)  
    } 
} 

private void processCursor(final Cursor cursor) { 
    new AsyncTask<Void, Void, Result> { 
     @Override 
     Result doInBackground(Void... params) { 
      while(cursor.isAfterLast() == false) { 
       // doing some costly things with cursor 
      } 
     } 
    }.execute(); 
} 

È possibile sia,

  1. segnalalo qualche modo il cursore per impedire che venga chiusa dal thread dell'interfaccia utente.

  2. Notificare al gestore che il cursore è ancora in uso.

  3. Clonare in modo che l'istanza clonata non venga chiusa dal gestore.

  4. Un'altra soluzione, ancora migliore?

Avendo questo post-elaborazione fatta sul thread UI non è assolutamente un'opzione, tuttavia, come può essere molto costoso.

+1

Si può sempre saltare il 'CursorLoader' e rendere la query iniziale + l'elaborazione costosa in' AsyncTask'. – Luksprog

+0

stai usando questo cursore per qualcos'altro? – njzk2

risposta

2

È possibile in qualche modo contrassegnare il cursore per impedire che venga chiuso dal thread dell'interfaccia utente?

No (beh, non senza riscrivere le API interne).

È possibile notificare al gestore che il cursore è ancora in uso?

Stessa risposta come sopra.

È possibile clonarlo in modo che l'istanza clonata non venga chiusa dal gestore?

questo suona tipo di disordine ... e c'è ancora la possibilità che il LoaderManager chiude il cursore prima di essere in grado di finire la clonazione.

Esiste una soluzione migliore?

Sì. Interroga un nuovo cursore invece di provare a riutilizzare quello che si passa a LoaderManager.

+0

Puoi essere più specifico? Dalla mia comprensione della tua risposta, dovrei ancora post-elaborare il nuovo Cursore, portando allo stesso problema ...? –

+0

Posso chiederti che cosa stai cercando di fare? Perché il tuo "post-processing" è legato insieme con il ciclo di vita di 'LoaderManager'? Perché non trattarli solo separatamente? Sarebbe molto più pulito in questo modo ... –

0

Uomo, sto affrontando lo stesso problema. Il modo è di annullare l'asynctask nel metodo onDestroy dell'attività.

private YourAsyncTask asyncTask 

@Override 
protected void onDestroy(){ 
    super.onDestroy(); 
    asyncTask.cancel(true); 
} 
Problemi correlati