6

Ho un problema semi-complicato e spero che qualcuno qui sarà in grado di aiutarmi.Android: notifyDataSetChanged() non sta aggiornando listview dopo il cambio di orientamento

In un evento click, creo un thread e avvio un'operazione di lunga durata basata sul metodo this. Dopo che il compito a lungo in esecuzione è completata, si fa un richiamo a un altro metodo, che fa un post al gestore:

@Override 
public void contentSearchModelChanged(Model_ContentSearch csm, ArrayList<Class_Reminder> newRemindersList) { 
    remindersList = newRemindersList; 
    mHandler.post(mUpdateDisplayRunnable); 
} 

che chiama un Runnable:

// post this to the Handler when the background thread completes 
private final Runnable mUpdateDisplayRunnable = new Runnable() { 
    public void run() { 
    updateDisplay(); 
    } 
}; 

Infine, ecco è ciò che il mio metodo updateDisplay() sta facendo:

private void updateDisplay() { 
    if (csModel.getState() != Model_ContentSearch.State.RUNNING) { 
     if(remindersList != null && remindersList.size() > 0){ 
       r_adapter = new ReminderAdapater(Activity_ContentSearch.this, remindersList, thisListView); 
       thisListView.setAdapter(r_adapter); 
       r_adapter.notifyDataSetChanged(); 
     } 
    } 
} 

Questo funziona magnificamente quando lo faccio normalmente. Tuttavia, se cambio l'orientamento mentre è in esecuzione l'operazione di lunga durata, non funziona. Rende correttamente la callback e la lista dei promemoria contiene degli elementi. Ma quando arriva a questa riga:

r_adapter.notifyDataSetChanged(); 

Non succede nulla. La cosa strana è che se faccio un altro invio e lo faccio eseguire di nuovo l'intero processo (senza cambiare orientamento), in realtà aggiorna la vista due volte, una volta per l'invio precedente e ancora per il successivo. Quindi la vista si aggiorna una volta con i risultati del primo invio, poi di nuovo con i risultati del secondo invio un secondo dopo. Quindi l'adattatore DID ottiene i dati, semplicemente non aggiorna la vista.

So che questo ha qualcosa a che fare con il cambiamento di orientamento, ma non posso per la vita di me capire perché. Qualcuno può aiutare? Oppure, qualcuno può suggerire un metodo alternativo per gestire i thread con i cambiamenti di orientamento?

Bara

risposta

6

Il problema è che quando si cambia orientamenti di una nuova attività è filata fin dall'inizio (onCreate). Il tuo lungo processo in esecuzione ha un controllo sull'attività vecchia (non più visibile). Stai aggiornando correttamente la vecchia attività ma poiché non è più sullo schermo, non la vedi.

Questo non è un problema facile da risolvere. C'è una biblioteca là fuori che può aiutarti comunque. Si chiama DroidFu. Ecco un post sul blog che (molto più accurato rispetto I) descrive la causa principale di ciò che state vedendo e come la biblioteca DroidFu combatte esso: http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/

Edit: (l'aggiunta di codice per il monitoraggio delle attività attivo)

In la classe di applicazione aggiungere questo:

private Activity _activeActivity; 
public void setActiveActivity(Activity activity) { 
    _activeActivity = activity; 
} 
public Activity getActiveActivity() { 
    return _activeActivity; 
} 

nelle vostre attività, aggiungere questo:

@Override 
public void onResume() { 
    super.onResume(); 
    ((MyApplicationClassName)getApplication()).setActiveActivity(this); 
} 

Ora è possibile ottenere l'activi attiva chiamare chiamando MyApplicationClassName.getActiveActivity();

Non è così che funziona DroidFu. DroidFu imposta l'attività attiva su onCreate ma non mi sembra molto robusta.

+0

Hmm ... sembra molto utile, ma non sembra esserci molta documentazione? Mi dispiacerebbe cambiare la mia implementazione all'uso di DroidFu e non sapere come risolvere un problema perché non è il modo "tipico" di fare le cose. – Bara

+0

Sì, sembra essere una vecchia biblioteca abbandonata ma la premessa sembra sana. Puoi farlo senza usare la libreria. Fondamentalmente l'oggetto Application tiene traccia dell'attività attiva (usando onResume). Quindi, quando si è pronti a notificare l'adattatore, si ottiene l'attività attiva dall'applicazione, verificare se si tratta di un'istanza dell'attività prevista e, in tal caso, trasmettere e notificare. –

+0

Qual è esattamente il codice per tracciare la "Attività attiva"? Cioè, dovrei fare qualcosa come CurrentActivity act = new CurrentActivity(); quindi passare atto alla classe Application? – Bara

1

Ho avuto un problema simile, avendo un thread che richiede tempo sendEmptyMessage a un gestore, che a sua volta ha chiamato notifyDataSetChanged su ListAdapter. Ha funzionato bene fino a quando ho cambiato orientamento.

Ho risolto il problema dichiarando un secondo gestore nel thread dell'interfaccia utente e ho inviato sendEmptyMessage al gestore, che a sua volta ha chiamato notifyDataSetChanged su ListAdapter. E avendo ListAdapter dichiarato come statico.

Sono un novizio, quindi non so se si tratta di una soluzione di brutto, ma ha funzionato per me ...

Da descrizione Jere.Jones vorrei assumere questo funziona come: il processo in esecuzione lungo sendEmptyMessage all'handle dalla vecchia Activity, che a sua volta sendEmptyMessage all'handle nella nuova Activity.

Problemi correlati