¿Por qué se llama CursorLoader onLoaderReset () después de la rotación del dispositivo?

Tengo una actividad principal A que utiliza un CursorLoader para consultar un DB. Esto creo en el método onCreate () de la actividad:

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... getSupportLoaderManager().initLoader(LOADER_MEASUREMENTS, null, A.this); } 

La actividad A también implementa las 3 callbacks para el CursorLoader:

 public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) public void onLoaderReset(Loader<Cursor> loader) 

Cuando hago girar el dispositivo, veo los métodos de ciclo de vida correctos ejecutados:

 A.onPause() A.onStop() A.onDestroy() A.onCreate() <-- re-connect to existing loader, onCreateLoader() not called A.onLoadFinished() A.onStart() A.onResume() 

A continuación, abro una subactividad B y roto mi dispositivo. Cuando termine B y regrese a la actividad AI vea el siguiente recorrido:

 B.onPause() A.onLoaderReset() <- why does this run? A.onDestroy() A.onCreate() A.onCreateLoader() <- now runs as loader is null A.onStart() ... 

¿Por qué se restablece mi cargador porque tuve Actividad B abierta y un dispositivo rotar? Sólo para agregar que la actividad B no tiene nada que ver con el DB o el CursorLoader.

Comprobé el código fuente LoaderManager que encontrarás en este método:

 /** * Stops and removes the loader with the given ID. If this loader * had previously reported data to the client through * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}. */ public abstract void destroyLoader(int id); 

Parece que el cargador se destruye al girar la pantalla (debido al cambio de configuración). LoaderManager llama internamente al método destroyLoader que a su vez llama al método de devolución de llamada onLoaderReset .

Parece que esto tiene algo que ver con LoaderManager y no mantener el estado de actividad.

LoaderManager es administrado por android.app.FragmentHostCallback y void doLoaderStop(boolean retain) en esta clase parece hacer la diferencia. Dependiendo del argumento, retain() o stop() sus cargadores.

Al cambiar la configuración en la actividad A (girando la pantalla) la actividad se destruye y se recrea de inmediato. En ActivityThread#handleRelaunchActivity() el valor mChangingConfigurations de la actividad se establece en true . Esto es importante, ya que al interrumpir su actividad en el cambio de configuración, esto se llama en Activity :

 final void performStop() { mDoReportFullyDrawn = false; mFragments.doLoaderStop(mChangingConfigurations /*retain*/); // ... } 

Usted puede intentar descender más profundamente en lo que sucede – su instalación del androide debe tener las fuentes y grep es impresionante hacer esto – pero resumiré el resto.

Exención de responsabilidad : No he comprobado a fondo lo siguiente, pero esto es lo que entiendo que está sucediendo.

Como se puede ver más arriba, cuando se considera que la actividad es apta para el relanzamiento, retendrá las cargadoras en lugar de detenerlas . Cuando gira la actividad A, los cargadores quedan retenidos. Cuando gira la actividad B, la actividad B se recrea de inmediato, mientras que la actividad A simplemente se destruye. Contrariamente a lo que ocurría antes, los cargadores se pararán.

Los cargadores detenidos sólo pueden ser destruidos y recreados según lo vea el LoaderManager, y esto es lo que está sucediendo a los suyos.

Si desea echar un buen vistazo, echa un vistazo a:

  • app/LoaderManager o v4/app/LoaderManager
  • app/FragmentHostCallback
  • Activity y ActivityThread

Simplemente puede establecer un punto de interrupción dentro de A.onLoaderReset () y ejecutar la aplicación en el modo de depuración para ver el seguimiento de la pila para la solución de problemas utilizando algo así como:

 class A extends Activity implements LoaderManager.LoaderCallbacks { @Override public void onLoaderReset(Loader loader) { try { // Constructs a new Exception that includes the current stack trace. throw new Exception(); } catch (Exception e) { Log.d("TAG", Log.getStackTraceString(e)); } } } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.