Descargo algunos datos de Internet en el hilo de fondo (uso AsyncTask) y visualizo un cuadro de diálogo de progreso durante la descarga. La orientación cambia, la actividad se reinicia y luego mi AsyncTask se completa: quiero cerrar el cuadro de diálogo de progreso e iniciar una nueva actividad. Pero llamar a despedirDialog a veces arroja una excepción (probablemente porque la Actividad fue destruida y la nueva Actividad aún no se ha iniciado).
¿Cuál es la mejor manera de manejar este tipo de problema (actualizar la interfaz de usuario desde el hilo de fondo que funciona incluso si el usuario cambia de orientación)? ¿Alguien de Google proporcionó alguna "solución oficial"?

Respuestas:
Paso # 1: Presente su
AsyncTaskunastaticclase anidada, o una clase completamente separada, pero no una (anidada no estática) de clase interna.Paso # 2:
AsyncTaskMantén el control aActivitytravés de un miembro de datos, establece a través del constructor y un establecedor.Paso # 3: Al crear el
AsyncTask, suministre la corrienteActivityal constructor.Paso # 4: En
onRetainNonConfigurationInstance(), devuelva elAsyncTask, después de separarlo de la actividad original, que ahora se va.Paso # 5:
onCreate()sigetLastNonConfigurationInstance()no lo estánull, envíalo a tuAsyncTaskclase y llama a tu setter para asociar tu nueva actividad con la tarea.Paso # 6: No se refiera al miembro de datos de actividad de
doInBackground().Si sigues la receta anterior, todo funcionará.
onProgressUpdate()yonPostExecute()se suspenden entre el inicioonRetainNonConfigurationInstance()y el final del siguienteonCreate().Aquí hay un proyecto de muestra que demuestra la técnica.
Otro enfoque es deshacerse del
AsyncTasky mover su trabajo a unIntentService. Esto es particularmente útil si el trabajo a realizar puede ser largo y debe continuar independientemente de lo que el usuario haga en términos de actividades (por ejemplo, descargar un archivo grande). Puede usar una transmisión ordenadaIntentpara que la actividad responda al trabajo que se está realizando (si todavía está en primer plano) o genere unaNotificationpara informar al usuario si el trabajo se ha realizado. Aquí hay una publicación de blog con más información sobre este patrón.fuente
onRetainNonConfigurationInstance()está en desuso y la alternativa sugerida es usarsetRetainInstance(), pero no devuelve un objeto. ¿Es posible manejarasyncTaskel cambio de configuración consetRetainInstance()?Fragmentbodega elAsyncTask. Tener elFragmentllamadosetRetainInstance(true)sobre sí mismo. Tener laAsyncTaskúnica charla con elFragment. Ahora, en un cambio de configuración,Fragmentno se destruye ni se recrea (aunque la actividad sí lo sea), por lo queAsyncTaskse retiene durante el cambio de configuración.La respuesta aceptada fue muy útil, pero no tiene un diálogo de progreso.
Afortunadamente para usted, lector, ¡he creado un ejemplo extremadamente completo y funcional de una AsyncTask con un diálogo de progreso !
fuente
Trabajé durante una semana para encontrar una solución a este dilema sin recurrir a la edición del archivo de manifiesto. Los supuestos para esta solución son:
Implementación
Deberá copiar los dos archivos que se encuentran al final de esta publicación en su espacio de trabajo. Solo asegúrate de que:
Todos tus
Activitymensajes deben extenderseBaseActivityEn
onCreate(),super.onCreate()debe llamarse después de inicializar los miembros a los que suASyncTasks debe acceder . Además, anulegetContentViewId()para proporcionar la identificación de diseño del formulario.Anular
onCreateDialog()como de costumbre para crear diálogos gestionados por la actividad.Consulte el código a continuación para ver una clase interna estática de muestra para realizar sus AsyncTasks. Puede almacenar su resultado en mResult para acceder más tarde.
Y finalmente, para lanzar tu nueva tarea:
¡Eso es! Espero que esta solución robusta ayude a alguien.
BaseActivity.java (organice las importaciones usted mismo)
SuperAsyncTask.java
fuente
Si.
La solución es más una propuesta de arquitectura de aplicación que un código .
Propusieron 3 patrones de diseño que permiten que una aplicación funcione sincronizada con un servidor, independientemente del estado de la aplicación (funcionará incluso si el usuario finaliza la aplicación, el usuario cambia de pantalla, la aplicación se termina, cualquier otro estado posible donde una operación de datos de fondo podría interrumpirse, esto lo cubre)
La propuesta se explica en el discurso de las aplicaciones de cliente REST de Android durante Google I / O 2010 por Virgil Dobjanschi. Dura 1 hora, pero vale la pena verlo.
La base de esto es abstraer las operaciones de red a una
Serviceque funciona de forma independiente a cualquieraActivityen la aplicación. Si está trabajando con bases de datos, el uso deContentResolveryCursorle proporcionaría un patrón de Observador listo para usar que es conveniente para actualizar la IU sin ninguna lógica adicional, una vez que haya actualizado su base de datos local con los datos remotos recuperados. Cualquier otro código posterior a la operación se ejecutará a través de una devolución de llamada pasada aService(yo uso unaResultReceiversubclase para esto).De todos modos, mi explicación es bastante vaga, definitivamente deberías ver el discurso.
fuente
Si bien la respuesta de Mark (CommonsWare) realmente funciona para los cambios de orientación, falla si la Actividad se destruye directamente (como en el caso de una llamada telefónica).
Puede manejar los cambios de orientación Y los raros eventos de Actividad destruidos utilizando un objeto Aplicación para hacer referencia a su ASyncTask.
Hay una excelente explicación del problema y la solución aquí :
El crédito va completamente a Ryan por resolver esto.
fuente
Después de 4 años, Google resolvió el problema simplemente llamando a setRetainInstance (true) en Activity onCreate. Conservará su instancia de actividad durante la rotación del dispositivo. También tengo una solución simple para Android anterior.
fuente
debe llamar a todas las acciones de actividad utilizando el controlador de actividad. Por lo tanto, si está en algún hilo, debe crear un Runnable y publicarlo utilizando el controlador de Activitie. De lo contrario, su aplicación se bloqueará a veces con una excepción fatal.
fuente
Esta es mi solución: https://github.com/Gotchamoh/Android-AsyncTask-ProgressDialog
Básicamente los pasos son:
onSaveInstanceStatepara guardar la tarea si aún se está procesando.onCreateMe sale la tarea si se guardó.onPausedescarto elProgressDialogsi se muestra.onResumeMuestro elProgressDialogsi la tarea aún se está procesando.fuente