2012-03-06 5 views
5

Sono in difficoltà da un po 'di tempo. Nel mio progetto ci sono diverse attività che includono un ListView e un adattatore personalizzato che estende BaseAdapter. Implementano anche alcune interfacce che di solito informano che i dati sono stati modificati.Chiamare il BaseAdapter di Android notifyDataSetChanged() da un metodo di callback del listener

Tuttavia, quando chiamo notifyDataSetChanged() dal metodo listener/interface implementato nella mia classe, ListView non viene aggiornato e nessuno dei metodi dell'adattatore viene chiamato (getCount(), getView()).

So che questo ha qualcosa a che fare con il fatto che viene chiamato notifyDataSetChanged(), intendo quale thread, ma non lo capisco e non trovo una spiegazione semplice di questo comportamento.

Come soluzione di questo problema ho utilizzare un gestore che chiama periodicamente e in quel metodo guardo se il valore booleano un 'needsToBeUpdated' è vero un metodo e chiamo il metodo notifyDataSetChanged() poi. Questo è brutto, però, e sono sicuro che ci deve essere un modo per farlo in modo asincrono.

Qualsiasi aiuto sarebbe apprezzato.

pseudo-codice di quello che sto parlando:

public class FriendsActivity extends Activity implements FriendsListener { 
private ListView mListView; 
private ArrayList<Friends> mFriendsList; 
private FriendsAdapter mFriendsAdapter; 
private boolean mNeedsToBeUpdated; 
private Handler mListUpdateHandler; 
private Runnable mListUpdateTask; 

onCreate() { 
    initViews(); 
    mFriendsAdapter = new FriendsAdapter(mFriendsList); 
    mListView.setAdapter(mFriendsAdapter); 
    SomeStaticClass.addFriendListener(this) 

    mNeedsToBeUpdated = false; 

    mListUpdateHandler = new Handler(); 
    mListUpdateHandler.removeCallbacks(mListUpdateTask); 
    mListUpdateHandler.postDelayed(mListUpdateTask, 10000); 

} 

onListenerMethod() { 
    updateFriendsList(); 
    mFriendsAdapter.updateDataSource(mFriendsList); 
    mFriendsAdapter.notifyDataSetChanged(); // THIS DOESN'T UPDATE THE VIEWS 
    mNeedsToBeUpdated = true; 
} 

protected void onResume() { 
    mListUpdateTask = new Runnable() { 
     public void run() { 
      if (mNeedsToBeUpdated) { 
       updateFriendsList(); 
       mFriendsAdapter.updateDataSource(mFriendsList); 
       mFriendsAdapter.notifyDataSetChanged(); // THIS UPDATES THE VIEWS 
       mListsRequireUpdating = false; 
      } 
      mListUpdateHandler.postDelayed(mListUpdateTask, 10000); 
     } 
    }; 
    mListUpdateHandler = new Handler(); 
    mListUpdateHandler.removeCallbacks(mListUpdateTask); 
    mListUpdateHandler.post(mListUpdateTask); 
    super.onResume(); 
} 

EDIT: Naturalmente mi ci sono voluti quasi nessun tempo per trovare la risposta, una volta che ho postato questo qui ...

odio per farlo ma ho messo un po 'più di sforzo nella ricerca di una risposta e penso di averlo trovato grazie a questo: - e questo: http://developer.android.com/reference/android/os/Handler.html

La soluzione è dolorosamente semplice. Non è possibile cambiare l'interfaccia utente in nessun altro thread ma il thread principale/dell'interfaccia utente. Ecco perché farlo nei metodi di callback non funziona. Tuttavia, la creazione di un gestore nel thread UI (ad esempio nel metodo onCreate()) lo collega al thread dell'interfaccia utente e può essere utilizzato in seguito per inviare eventi a questo thread.

mListUpdateHandler = new Handler(); 

Quindi, è necessaria una classe interna implementa l'interfaccia Runnable dove il ritocco UI è fatto.

class UpdateListRunnable implements Runnable { 
     @Override 
     public void run() { 
      Log.i(LOGTAG, "UpdateListRunnable"); 
      FriendsActivity.this.updateLists();    
     } 
    } 

Infine, nel metodo di callback abbiamo posto l'evento con classe UpdateListRunnable verso il filo principale tramite il Handler:

@Override 
    public void entriesUpdated(Collection<String> entries) { 
     Log.i(LOGTAG, "entriesUpdated"); 
     for (String entry : entries) { 
      Log.i(LOGTAG, "entry: " + entry); 
     } 
     mListUpdateHandler.post(new UpdateListRunnable()); 
    } 

Grazie a ciò le upadteLists() metodo viene eseguito nel thread UI e tutto funziona come un fascino.

risposta

0

Ho avuto lo stesso problema con la mia applicazione. La prima soluzione era usare gli Handler. Il più elegante è usare i caricatori - controlla http://developer.android.com/guide/components/loaders.html! Il pacchetto di compatibilità per le versioni precedenti di Android li rende disponibili per Android 1.6+