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 (…).
- Androide. Yor propio progreso-bar?
- ¿Cuál es la diferencia entre Progressbar y ProgressDialog?
- Barra de progreso de Android en ImageView
- Android cómo actualizar el valor de ProgressBar?
- Mostrar ProgressBar durante cierto tiempo en Android
- Descargar imágenes con AsyncTask
- ¿Cómo dar una barra de progreso para la descarga?
- Cómo dejar de cambiar la orientación cuando una barra de progreso está girando en android
- android progressBar no actualiza el progreso view / drawable
- ¿Cómo puedo hacer una barra de progreso personalizada en la barra de acción?
- ¿Cómo eliminar el número de barra de progreso en la parte inferior de la barra de progreso?
- ¿Cómo mostrar un ProgressBar en una vista mientras realizas algún trabajo?
- Android: ¿Cómo puedo mostrar la barra de progreso al cargar datos en WebView?
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!
- ListView expandir animación para elementos sólo funciona después del segundo clic
- UiAutomator volcado para Lollipop Lost WebView Ver jerarquía