AsyncTask, Fragmentos, Vistas y Backstacks

He estado usando este patrón para un poco. Aquí está un ejemplo muy artificial de un indicador de progreso AsyncTask +:

new AsyncTask<Void, Void, Void>() { WeakReference<MyFragment> weakFragment = new WeakReference<MyFragment>(MyFragment.this); @Override protected void onPreExecute() { Fragment fragment = weakFragment.get(); if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.VISIBLE); } @Override protected Document doInBackground(Void... params) { Fragment fragment = weakFragment.get(); if(fragment == null) return null; // Do something ... } @Override protected void onPostExecute() { Fragment fragment = weakFragment.get(); if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.GONE); } }.execute(); 

Funciona bien con los cambios de orientación, pero he notado que el fragmento no es nulo y fragmento.getView () siendo nulo cuando pop el fragmento de la backstack. Eso obviamente hace que esto se bloquee. ¿Qué enfoque están usando? No puedo encontrar una solución perfecta en línea. Nota importante, esto está en un fragmento y llamo setRetainInstance(true); Sobre ese fragmento en su onActivityCreated (…).

AsyncTask es una tarea asincrónica que significa que normalmente no sabes cuándo se completa y cuando llama a onPostExecute() . Creo que tu problema está aquí. Cuando gira el dispositivo, su asynctask no ha terminado todavía y su vista de fragmento se destruye y vuelve a crear de nuevo muy rápidamente mientras asynctask está en el hilo de trabajo y cuando ha hecho su trabajo su fragmento tiene una vista y el valor de retorno de getView no es null Pero si el tiempo de rotación toma mucho obtendrá null porque el AsyncTask ha terminado pero su fragmento no tiene ninguna vista. Ahora este escenario es exactamente sucede a su backstack Cuando usted empuja su fragmento a la backstack su vista se destruye ( mirar la imagen ), pero el fragmento en sí no es (el fragmento vuelve a la disposición de backstack). Ahora su AsyncTask termina y llame a su método getView fragment y no tiene ninguna view para que obtenga NPE .

Mi solución:

Primero debes usar WeakReference<ProgressBar> lugar de WeakReference<MyFragment> y en onPostExecute() comprobar si es nulo o no, si es nulo no hacer nada porque el valor predeterminado es invisible si no es null call setVisibility(View.GONE) .

Actualizar:

El fragmento está vivo pero la vista se ha dealloc'd. es posible?

Sí, solo mira la figura2 del enlace. Cuando el fragmento está activo (casilla verde), the fragment added to back stack fragmento de la the fragment added to back stack va a onPause , onStop onDestroyView . Entonces, cuando el fragmento aparece de la pila de atrás va derecho a onCreateView el enlace de flecha con este texto: the fragment returns to the layout from backstack .

Para confirmar mi respuesta usted puede crear un AsyncTask y llamar SystemClock.sleep(30000) dentro de su doInbackground . Ahora usted puede empujar su fragmento en el backstack y aparece de backstack sin excepción porque el asynctask no ha terminado y cuando llamará onPostExecute() su fragmento ya tiene una vista.

Otra cosa buena que puedes ver es setRetainInstance

Esto sólo puede usarse con fragmentos que no estén en la pila trasera.

Así que cuando usted empuja su fragmento en la pila de la espalda puede destruir por completo y puede obtener nueva referencia de fragmento cuando aparece. Pero cuando se utiliza setRetainInstance(true); Para los cambios de configuración su fragmento se retiene a través de la recreación de la actividad, lo que significa que es el mismo fragmento y onCreate no se llama. Y esto es muy importante porque si inicia el AsyncTask en el método onCreate , cuando onCreate el fragmento en la pila trasera y lo onCreate , puede tener un nuevo fragmento y esto significa que se onCreate método onCreate y se dispara otro AsyncTask . Eso significa que usted no tiene ningún control sobre el número de llamada AsyncTask s así que AsyncTask cuidado con las fugas de memoria!

  • (ProgressBar) findViewById (R.id.ProgressBar) devuelve null
  • Barra de progreso de Android en el botón
  • Cómo cambiar el color de la barra de progreso en Android? - (Traté de una manera, y no funciona)
  • Fondo circular de ProgressBar: Android Xamarin
  • ¿Cómo mostrar la barra de progreso en cada elemento de vista de lista?
  • Android barra de progreso horizontal?
  • Animar la actualización de ProgressBar en Android
  • Cómo conseguir la barra de progreso indeterminada más suave usada en la aplicación Android de Gmail
  • Necesito saber cuánto bytes se ha cargado para actualizar una barra de progreso android
  • ¿Cómo cambiar el color en la barra de progreso circular?
  • ¿Hay una barra de progreso negra para ser visible en un fondo blanco?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.