2012-03-06 12 views
5

He estado luchando con esto desde hace un tiempo. En mi proyecto hay varias actividades que incluyen un ListView y un adaptador personalizado que extiende BaseAdapter. También implementan algunas interfaces que generalmente informan que los datos han sido cambiados.Llamando a BaseAdapter de Android notifyDataSetChanged() desde un método de devolución de llamada de escucha

Sin embargo, cuando llamo a notifyDataSetChanged() desde el método listener/interface implementado en mi clase, ListView no se actualiza y ninguno de los métodos del adaptador se llama (getCount(), getView()).

Sé que esto tiene algo que ver con el hecho de que se llame a notifyDataSetChanged(), me refiero a qué hilo, pero no lo entiendo del todo y no pude encontrar una explicación directa de este comportamiento.

Como solución a este problema utilizo un controlador que llama a un método periódicamente y en ese método miro si un valor booleano 'needsToBeUpdated' es verdadero y llamo entonces al método notifyDataSetChanged(). Esto es feo, sin embargo, y estoy seguro de que debe haber una manera de hacerlo de forma asíncrona.

Cualquier ayuda sería apreciada.

Pseudocódigo de lo que estoy hablando:

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: Por supuesto que me llevó casi sin tiempo para encontrar la respuesta, una vez que he publicado esta aquí ...

odio para hacerlo, pero puse un poco más de esfuerzo en buscar una respuesta y creo que lo encontré gracias a esto: http://developer.android.com/resources/articles/painless-threading.html - y esto: http://developer.android.com/reference/android/os/Handler.html

La solución es dolorosamente simple. No es posible cambiar la UI en ningún otro hilo, excepto el hilo principal/UI. Es por eso que hacerlo en los métodos de devolución de llamada no funciona. Sin embargo, la creación de un controlador en el subproceso de interfaz de usuario (por ejemplo, en el método onCreate()) lo conecta al subproceso de la interfaz de usuario y se puede utilizar más adelante para publicar eventos en este tema.

mListUpdateHandler = new Handler(); 

Luego, se necesita una clase interna que implementa la interfaz Runnable donde se realiza el ajuste de la interfaz de usuario.

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

Finalmente, en el método de devolución de llamada que publiquemos el evento con clase UpdateListRunnable a cabo con el hilo principal a través de la 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()); 
    } 

Gracias a que los upadteLists() se ejecuta método en el hilo UI y todo funciona como un encanto.

Respuesta

Cuestiones relacionadas