6

Tengo un problema semi complicado y espero que alguien aquí pueda ayudarme.Android: notifyDataSetChanged() no actualiza la lista vista después de cambiar la orientación

En un evento de clic, creo un hilo y comienzo una operación de larga ejecución basada en el método this. Una vez completada la tarea de larga duración, lo hace una devolución de llamada a otro método, que hace una entrada al controlador:

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

que llama a un Ejecutable:

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

Por último, aquí es lo que mi El método updateDisplay() lo está haciendo:

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(); 
     } 
    } 
} 

Esto funciona muy bien cuando hago esto normalmente. Sin embargo, si cambio la orientación mientras se ejecuta la operación de larga ejecución, no funciona. Realiza la devolución de llamada correctamente, y remindersList tiene elementos. Pero cuando llega a esta línea:

r_adapter.notifyDataSetChanged(); 

No pasa nada. Lo extraño es que si hago otro envío y hago que vuelva a ejecutar todo el proceso (sin cambiar la orientación), en realidad actualiza la vista dos veces, una para el envío anterior y otra para el siguiente. Entonces, la vista se actualiza una vez con los resultados del primer envío, luego nuevamente con los resultados del segundo envío, un segundo después. Entonces, el adapater obtuvo los datos, simplemente no refresca la vista.

Sé que esto tiene algo que ver con el cambio de orientación, pero no puedo entender por qué. ¿Alguien puede ayudar? O, ¿alguien puede sugerir un método alternativo para manejar hilos con cambios de orientación?

Bara

Respuesta

6

El problema es que cuando se cambia orientaciones una nueva actividad se hace girar hacia arriba desde el principio (onCreate). Su proceso de ejecución prolongada tiene un control de la actividad anterior (ya no visible). Estás actualizando correctamente la actividad anterior, pero como ya no está en la pantalla, no la ves.

No es un problema fácil de arreglar. Hay una biblioteca por ahí que puede ayudarte. Se llama DroidFu. Aquí es un blog que (con mucha más precisión que yo) describe la causa raíz de lo que están viendo y cómo la biblioteca DroidFu lo combate: http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/

Editar: (Adición de código para el seguimiento de la actividad activo)

En la clase de aplicación añadir lo siguiente:

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

en sus actividades, añadir lo siguiente:

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

Ahora usted puede conseguir la activi activa ty llamando a MyApplicationClassName.getActiveActivity();

Así no es como lo hace DroidFu. DroidFu establece la actividad activa en onCreate, pero no creo que sea muy robusto.

+0

Hmm ... eso parece muy útil, pero parece que no hay mucha documentación? No me gustaría cambiar mi implementación al uso de DroidFu y no sé cómo resolver un problema porque no es la forma "típica" de hacer las cosas. – Bara

+0

Sí, parece ser una antigua biblioteca abandonada, pero la premisa parece sólida. Puedes hacer esto sin usar la biblioteca. Básicamente, el objeto Aplicación realiza un seguimiento de la Actividad activa (usando onResume). Luego, cuando esté listo para notificar a su adaptador, obtiene la Actividad activa de la Aplicación, verifique si es una instancia de su actividad esperada y, de ser así, envíe y notifique. –

+0

¿Cuál es exactamente el código para rastrear la "Actividad activa"? Es decir, ¿debería estar haciendo algo como CurrentActivity act = new CurrentActivity(); luego pasar acto a la clase de Aplicación? – Bara

1

Tuve un problema similar, teniendo un hilo que consume tiempo sendEmptyMessage a un controlador, que a su vez llama a notifyDataSetChanged en un ListAdapter. Funcionó bien hasta que cambié de orientación.

Lo resolví al declarar un segundo controlador en el hilo de la interfaz de usuario y hacer que el primer controlador envíeEmptyMessage a este controlador, que a su vez llamó a notifyDataSetChanged en el ListAdapter. Y tener el ListAdapter declarado como estático.

Soy un novato, así que no sé si se trata de una solución feo, pero funcionó para mí ...

Por la descripción Jere.Jones yo supongo que esto funciona como: El proceso de larga duración sendEmptyMessage al manejador de la actividad anterior, que a su vez envíaEmptyMessage al manejador en la nueva actividad.

Cuestiones relacionadas