Mi programa realiza alguna actividad de red en un hilo de fondo. Antes de comenzar, aparece un cuadro de diálogo de progreso. El diálogo se descarta en el controlador. Todo esto funciona bien, excepto cuando la orientación de la pantalla cambia mientras el cuadro de diálogo está activo (y el hilo de fondo continúa). En este punto, la aplicación se bloquea o se interrumpe, o entra en una etapa extraña en la que la aplicación no funciona en absoluto hasta que se hayan eliminado todos los hilos.
¿Cómo puedo manejar el cambio de orientación de la pantalla con gracia?
El siguiente código de muestra coincide aproximadamente con lo que hace mi programa real:
public class MyAct extends Activity implements Runnable {
public ProgressDialog mProgress;
// UI has a button that when pressed calls send
public void send() {
mProgress = ProgressDialog.show(this, "Please wait",
"Please wait",
true, true);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
Thread.sleep(10000);
Message msg = new Message();
mHandler.sendMessage(msg);
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgress.dismiss();
}
};
}
Apilar:
E/WindowManager( 244): Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): android.view.WindowLeaked: Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): at android.view.ViewRoot.<init>(ViewRoot.java:178)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:147)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:90)
E/WindowManager( 244): at android.view.Window$LocalWindowManager.addView(Window.java:393)
E/WindowManager( 244): at android.app.Dialog.show(Dialog.java:212)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:103)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:91)
E/WindowManager( 244): at MyAct.send(MyAct.java:294)
E/WindowManager( 244): at MyAct$4.onClick(MyAct.java:174)
E/WindowManager( 244): at android.view.View.performClick(View.java:2129)
E/WindowManager( 244): at android.view.View.onTouchEvent(View.java:3543)
E/WindowManager( 244): at android.widget.TextView.onTouchEvent(TextView.java:4664)
E/WindowManager( 244): at android.view.View.dispatchTouchEvent(View.java:3198)
Intenté descartar el cuadro de diálogo de progreso en onSaveInstanceState, pero eso solo evita un bloqueo inmediato. El subproceso de fondo aún continúa y la interfaz de usuario está en estado parcialmente dibujado. Necesita matar toda la aplicación antes de que comience a funcionar nuevamente.
fuente
Respuestas:
Cuando cambie de orientación, Android creará una nueva vista. Probablemente te estés bloqueando porque tu hilo de fondo está tratando de cambiar el estado del anterior. (También puede estar teniendo problemas porque su hilo de fondo no está en el hilo de la interfaz de usuario)
Sugeriría hacer que mHandler sea volátil y actualizarlo cuando cambie la orientación.
fuente
Editar: los ingenieros de Google no recomiendan este enfoque, como lo describe Dianne Hackborn (también conocido como hackbod ) en esta publicación de StackOverflow . Mira esta publicación de blog para más información.
Debe agregar esto a la declaración de actividad en el manifiesto:
entonces parece
El problema es que el sistema destruye la actividad cuando ocurre un cambio en la configuración. Ver cambios de configuración .
Poner eso en el archivo de configuración evita que el sistema destruya su actividad. En su lugar, invoca el
onConfigurationChanged(Configuration)
método.fuente
orientation
, hay muchas más razones para que cambie la configuración:keyboardHidden
(ya he editado la respuesta wiki),uiMode
(Por ejemplo, entrar o salir del modo de automóvil; cambio de modo nocturno), etc. Ahora me pregunto si esto es realmente Una buena respuesta.Se me ocurrió una solución sólida para estos problemas que se ajusta a la 'forma Android' de las cosas. Tengo todas mis operaciones de larga duración utilizando el patrón IntentService.
Es decir, mis intentos actividades de difusión, el IntentService hace el trabajo, guarda los datos en la base de datos y luego difunde pegajosas intenciones. La parte adhesiva es importante, de modo que incluso si la Actividad se detuvo durante el tiempo después de que el usuario inició el trabajo y pierde la transmisión en tiempo real desde IntentService, aún podemos responder y recoger los datos de la Actividad que realiza la llamada.
ProgressDialog
s puede funcionar muy bien con este patrónonSaveInstanceState()
.Básicamente, debe guardar un indicador de que tiene un cuadro de diálogo de progreso ejecutándose en el paquete de instancias guardadas. No guarde el objeto de diálogo de progreso porque esto filtrará toda la Actividad. Para tener un control persistente del diálogo de progreso, lo almaceno como una referencia débil en el objeto de la aplicación. En el cambio de orientación o cualquier otra cosa que haga que la Actividad se detenga (llamada telefónica, usuario llegue a casa, etc.) y luego se reanude, descarto el diálogo anterior y vuelvo a crear un diálogo nuevo en la Actividad recién creada.
Para diálogos de progreso indefinidos, esto es fácil. Para el estilo de barra de progreso, debe colocar el último progreso conocido en el paquete y cualquier información que esté utilizando localmente en la actividad para realizar un seguimiento del progreso. Al restaurar el progreso, utilizará esta información para volver a generar la barra de progreso en el mismo estado que antes y luego actualizar según el estado actual de las cosas.
Para resumir, colocar tareas de larga duración en un IntentService junto con un uso juicioso de le
onSaveInstanceState()
permite realizar un seguimiento eficiente de los diálogos y restaurarlos a lo largo de los eventos del ciclo de vida de la Actividad. Los bits relevantes del código de actividad están a continuación. También necesitará lógica en su BroadcastReceiver para manejar adecuadamente las intenciones de Sticky, pero eso está fuera del alcance de esto.fuente
Me encontré con el mismo problema. Mi actividad necesita analizar algunos datos de una URL y es lenta. Entonces creo un hilo para hacerlo, luego muestro un diálogo de progreso. Dejo que el hilo publique un mensaje en el hilo de la interfaz de usuario
Handler
cuando esté terminado. EnHandler.handleMessage
, obtengo el objeto de datos (listo ahora) del hilo y lo relleno en la interfaz de usuario. Entonces es muy similar a tu ejemplo.Después de muchas pruebas y errores, parece que encontré una solución. Al menos ahora puedo rotar la pantalla en cualquier momento, antes o después de que el hilo esté terminado. En todas las pruebas, el cuadro de diálogo se cierra correctamente y todos los comportamientos son los esperados.
Lo que hice se muestra a continuación. El objetivo es llenar mi modelo de datos (
mDataObject
) y luego completarlo en la interfaz de usuario. Debe permitir la rotación de la pantalla en cualquier momento sin sorpresa.Eso es lo que me funciona. No sé si este es el método "correcto" diseñado por Android: afirman que esta "actividad de destruir / recrear durante la rotación de la pantalla" en realidad hace las cosas más fáciles, así que supongo que no debería ser demasiado complicado.
Avíseme si ve un problema en mi código. Como se dijo anteriormente, realmente no sé si hay algún efecto secundario.
fuente
onRetainNonConfigurationInstance()
ygetLastNonConfigurationInstance()
me ayudó a resolver mi problema. ¡Pulgares hacia arriba!El problema original percibido era que el código no sobreviviría a un cambio de orientación de la pantalla. Aparentemente, esto se "resolvió" haciendo que el programa manejara el cambio de orientación de la pantalla, en lugar de dejar que el marco de la interfaz de usuario lo hiciera (llamando a onDestroy).
Diría que si el problema subyacente es que el programa no sobrevivirá en Destroy (), entonces la solución aceptada es solo una solución que deja al programa con otros problemas y vulnerabilidades graves. Recuerde que el marco de Android establece específicamente que su actividad está en riesgo de ser destruida casi en cualquier momento debido a circunstancias fuera de su control. Por lo tanto, su actividad debe poder sobrevivir en onDestroy () y en onCreate () posterior por cualquier motivo, no solo un cambio de orientación de la pantalla.
Si va a aceptar manejar los cambios de orientación de la pantalla usted mismo para resolver el problema del OP, debe verificar que otras causas de onDestroy () no generen el mismo error. ¿Eres capaz de hacer esto? Si no, me preguntaría si la respuesta "aceptada" es realmente muy buena.
fuente
Mi solución fue extender la
ProgressDialog
clase para obtener la míaMyProgressDialog
.Redefiní
show()
ydismiss()
métodos para bloquear la orientación antes de mostrarlaDialog
y desbloquearla nuevamente cuandoDialog
se descarta. Entonces, cuandoDialog
se muestra y cambia la orientación del dispositivo, la orientación de la pantalla permanece hasta quedismiss()
se llama, luego la orientación de la pantalla cambia de acuerdo con los valores del sensor / orientación del dispositivo.Aquí está mi código:
fuente
Me enfrenté a este mismo problema y se me ocurrió una solución que no se invocaba con ProgressDialog y obtengo resultados más rápidos.
Lo que hice fue crear un diseño que tiene una barra de progreso.
Luego, en el método onCreate, haga lo siguiente
Luego haga la tarea larga en un hilo, y cuando termine, haga que Runnable configure la vista de contenido en el diseño real que desea usar para esta actividad.
Por ejemplo:
Esto es lo que hice, y descubrí que se ejecuta más rápido que mostrar el ProgressDialog y es menos intrusivo y tiene una mejor apariencia en mi opinión.
Sin embargo, si desea utilizar ProgressDialog, esta respuesta no es para usted.
fuente
setContentView(R.layout.my_layout);
No es suficiente; es necesario configurar todos los oyentes, datos de reposición, etc.Descubrí una solución a esto que aún no he visto en ningún otro lado. Puede usar un objeto de aplicación personalizado que sepa si tiene tareas en segundo plano en lugar de intentar hacer esto en la actividad que se destruye y se recrea en el cambio de orientación. Blogueé sobre esto aquí .
fuente
Application
se usa normalmente para mantener un estado de aplicación global. No digo que no funcione, pero parece demasiado complicado. Del documento "Normalmente no hay necesidad de subclase Aplicación". Prefiero en gran medida la respuesta de sonxurxo.Voy a aportar mi enfoque para manejar este problema de rotación. Esto puede no ser relevante para OP ya que no lo está usando
AsyncTask
, pero tal vez otros lo encuentren útil. Es bastante simple pero parece hacer el trabajo por mí:Tengo una actividad de inicio de sesión con una
AsyncTask
clase anidada llamadaBackgroundLoginTask
.En mi caso
BackgroundLoginTask
, no hago nada fuera de lo común, excepto agregar un cheque nulo alProgressDialog
descartar la llamada :Esto es para manejar el caso donde la tarea en segundo plano finaliza mientras
Activity
no está visible y, por lo tanto, el diálogo de progreso ya ha sido descartado por elonPause()
método.A continuación, en mi
Activity
clase principal , creo identificadores estáticos globales para miAsyncTask
clase y miProgressDialog
(elAsyncTask
, anidado, puede acceder a estas variables):Esto tiene dos propósitos: en primer lugar, me permite
Activity
acceder siempre alAsyncTask
objeto, incluso desde una nueva actividad posterior a la rotación. En segundo lugar, me permiteBackgroundLoginTask
acceder y descartarProgressDialog
incluso después de una rotación.A continuación, agrego esto a
onPause()
, haciendo que el cuadro de diálogo de progreso desaparezca cuando nuestroActivity
abandona el primer plano (evitando ese feo bloqueo de "cierre forzado"):Finalmente, tengo lo siguiente en mi
onResume()
método:Esto permite
Dialog
que reaparezca después de que se vuelve aActivity
crear.Aquí está toda la clase:
De ninguna manera soy un desarrollador experimentado de Android, así que siéntase libre de comentar.
fuente
Mueva la tarea larga a una clase separada. Impleméntelo como un patrón sujeto-observador. Cada vez que se crea la actividad, regístrese y, al cerrar, anule el registro con la clase de tarea. La clase de tarea puede usar AsyncTask.
fuente
El truco consiste en mostrar / descartar el diálogo dentro de AsyncTask durante onPreExecute / onPostExecute como de costumbre, aunque en caso de cambio de orientación cree / muestre una nueva instancia del diálogo en la actividad y pase su referencia a la tarea.
fuente
Lo he hecho así:
También puedes intentar y hacerme saber que funciona para ti o no
fuente
Si crea un fondo
Service
que hace todo el trabajo pesado (solicitudes / respuestas de tcp, desorganización), elView
yActivity
puede ser destruido y recreado sin filtrar la ventana o perder datos. Esto permite el comportamiento recomendado de Android, que es destruir una Actividad en cada cambio de configuración (por ejemplo, para cada cambio de orientación).Es un poco más complejo, pero es la mejor manera de invocar la solicitud del servidor, el procesamiento previo / posterior de datos, etc.
Incluso puede usar su
Service
para poner en cola cada solicitud a un servidor, por lo que es fácil y eficiente manejar esas cosas.La guía de desarrollo tiene un capítulo
Services
completo sobre .fuente
Service
es más trabajo que unAsyncTask
pero puede ser un mejor enfoque en algunas situaciones. No es necesariamente mejor, ¿verdad? Dicho esto, no entiendo cómo esto resuelve el problema de loProgressDialog
que se filtra desde el principalActivity
. ¿Dónde instancias elProgressDialog
? ¿Dónde lo descartas?Tengo una implementación que permite que la actividad se destruya en un cambio de orientación de la pantalla, pero aún así destruye el diálogo en la actividad recreada con éxito. Utilizo
...NonConfigurationInstance
para adjuntar la tarea en segundo plano a la actividad recreada. El marco normal de Android maneja la recreación del diálogo en sí, no se cambia nada allí.Subclase AsyncTask agregando un campo para la actividad 'propietaria' y un método para actualizar este propietario.
En mi clase de actividad, agregué un campo que hace
backgroundTask
referencia a la tarea de fondo "propiedad" y actualizo este campo cononRetainNonConfigurationInstance
ygetLastNonConfigurationInstance
.Sugerencias para seguir mejorando:
backgroundTask
referencia en la actividad después de que la tarea haya finalizado para liberar cualquier memoria u otros recursos asociados con ella.ownerActivity
referencia en la tarea de fondo antes de que la actividad se destruya en caso de que no se vuelva a crear de inmediato.BackgroundTask
interfaz y / o colección para permitir que se ejecuten diferentes tipos de tareas desde la misma actividad propietaria.fuente
Si mantiene dos diseños, todos los subprocesos de la interfaz de usuario deben terminarse.
Si usa AsynTask, puede llamar fácilmente al
.cancel()
método dentro delonDestroy()
método de la actividad actual.Para AsyncTask, lea más en la sección "Cancelar una tarea" aquí .
Actualización: condición agregada para verificar el estado, ya que solo se puede cancelar si está en estado de ejecución. También tenga en cuenta que AsyncTask solo se puede ejecutar una vez.
fuente
Intenté implementar la solución de jfelectron porque es una " solución sólida para estos problemas que se ajusta a la" forma de Android "de las cosas ", pero llevó un tiempo buscar y reunir todos los elementos mencionados. Terminé con esta solución ligeramente diferente, y creo que más elegante, publicada aquí en su totalidad.
Utiliza un IntentService disparado desde una actividad para realizar la tarea de ejecución larga en un hilo separado. El servicio devuelve Intenciones de difusión fijas a la actividad que actualiza el diálogo. La Actividad usa showDialog (), onCreateDialog () y onPrepareDialog () para eliminar la necesidad de que se pasen datos persistentes en el objeto de la aplicación o el paquete savedInstanceState. Esto debería funcionar sin importar cómo se interrumpa su aplicación.
Clase de actividad:
Clase IntentService:
Entradas de archivo de manifiesto:
Antes de la sección de aplicación:
sección de aplicación interior
fuente
Esta es mi solución propuesta:
void showProgressDialog()
puede agregar un método a la interfaz de escucha de actividad de fragmentos para este propósito.fuente
Me enfrenté a la misma situación. Lo que hice fue obtener solo una instancia para mi diálogo de progreso en toda la aplicación.
Primero, creé una clase DialogSingleton para obtener solo una instancia (patrón Singleton)
Como muestro en esta clase, tengo el diálogo de progreso como atributo. Cada vez que necesito mostrar un diálogo de progreso, obtengo una instancia única y creo un nuevo ProgressDialog.
Cuando termino con la tarea en segundo plano, vuelvo a llamar a la instancia única y descarto su diálogo.
Guardo el estado de la tarea en segundo plano en mis preferencias compartidas. Cuando giro la pantalla, pregunto si tengo una tarea ejecutándose para esta actividad: (onCreate)
Cuando empiezo a ejecutar una tarea en segundo plano:
Cuando termino de ejecutar una tarea en segundo plano:
Espero que ayude.
fuente
Esta es una pregunta muy antigua que apareció en la barra lateral por alguna razón.
Si la tarea en segundo plano solo necesita sobrevivir mientras la actividad está en primer plano, la "nueva" solución es alojar el subproceso en segundo plano (o, preferiblemente,
AsyncTask
) en un fragmento retenido , como se describe en esta guía del desarrollador y numerosas preguntas y respuestas .Un fragmento retenido sobrevive si la actividad se destruye por un cambio de configuración, pero no cuando la actividad se destruye en segundo plano o en la pila. Por lo tanto, la tarea en segundo plano aún debe interrumpirse si
isChangingConfigurations()
es falsaonPause()
.fuente
Estoy más fresco en Android e intenté esto y funcionó.
fuente
Lo he intentado TODO. Pasé días experimentando. No quería bloquear la rotación de la actividad. Mi escenario fue:
El problema era que, al girar la pantalla, todas las soluciones del libro fallaban. Incluso con la clase AsyncTask, que es la forma correcta de Android de lidiar con estas situaciones. Al girar la pantalla, el contexto actual con el que está trabajando el hilo inicial desaparece y eso se confunde con el diálogo que se muestra. El problema siempre fue el Diálogo, sin importar cuántos trucos agregué al código (pasar nuevos contextos a hilos en ejecución, retener estados de hilo a través de rotaciones, etc.). La complejidad del código al final siempre fue enorme y siempre había algo que podía salir mal.
La única solución que funcionó para mí fue el truco Actividad / Diálogo. Es simple y genial y es a prueba de rotación:
En lugar de crear un cuadro de diálogo y pedir que se muestre, cree una actividad que se haya establecido en el manifiesto con android: theme = "@ android: style / Theme.Dialog". Entonces, solo parece un diálogo.
Reemplace showDialog (DIALOG_ID) con startActivityForResult (yourActivityDialog, yourCode);
Use onActivityResult en la Actividad de llamada para obtener los resultados del subproceso en ejecución (incluso los errores) y actualizar la IU.
En su 'ActivityDialog', use hilos o AsyncTask para ejecutar tareas largas y onRetainNonConfigurationInstance para guardar el estado del "diálogo" al girar la pantalla.
Esto es rápido y funciona bien. Todavía uso diálogos para otras tareas y AsyncTask para algo que no requiere un diálogo constante en la pantalla. Pero con este escenario, siempre voy por el patrón Actividad / Diálogo.
Y no lo intenté, pero incluso es posible bloquear la rotación de esa Actividad / Diálogo, cuando el hilo se está ejecutando, acelerando las cosas, mientras que permite que la Actividad de llamada gire.
fuente
Intent
, que es más restrictivo que elObject
permitido porAsyncTask
En estos días hay una forma mucho más clara de manejar este tipo de problemas. El enfoque típico es:
1. Asegúrese de que sus datos estén separados adecuadamente de la interfaz de usuario:
Todo lo que sea un proceso en segundo plano debe estar retenido
Fragment
(configúrelo conFragment.setRetainInstance()
. Esto se convierte en su 'almacenamiento de datos persistente' donde se guarda todo lo basado en datos que le gustaría retener. Después del evento de cambio de orientación,Fragment
aún será accesible en su original estado a través de unaFragmentManager.findFragmentByTag()
llamada (cuando lo cree, debe darle una etiqueta, no una ID, ya que no está adjunto a aView
).Consulte la guía desarrollada Manejo de cambios en tiempo de ejecución para obtener información sobre cómo hacer esto correctamente y por qué es la mejor opción.
2. Asegúrese de interactuar de manera correcta y segura entre los procesos en segundo plano y su IU:
Debe revertir su proceso de vinculación. En este momento, su proceso en segundo plano se une a un
View
- en su lugar,View
debería estar adjuntándose al proceso en segundo plano. Tiene más sentido ¿verdad? LaView
acción de 's depende del proceso en segundo plano, mientras que el proceso en segundo plano no depende delView
. Esto significa cambiar el enlace a unaListener
interfaz estándar . Digamos que su proceso (sea cual sea la clase que es - si se trata de unaAsyncTask
,Runnable
o lo que sea) define unaOnProcessFinishedListener
, cuando el proceso se realiza debe llamar a ese oyente si existe.Esta respuesta es una buena descripción concisa de cómo hacer oyentes personalizados.
3. Enlace su interfaz de usuario al proceso de datos cada vez que se crea la interfaz de usuario (incluidos los cambios de orientación):
Ahora debe preocuparse por interactuar la tarea en segundo plano con cualquiera que sea su
View
estructura actual . Si está manejando sus cambios de orientación correctamente (no es elconfigChanges
truco que la gente siempre recomienda),Dialog
el sistema recreará su sistema. Esto es importante, significa que en el cambio de orientación, todos losDialog
métodos de ciclo de vida se recuperan. Entonces, en cualquiera de estos métodos (onCreateDialog
generalmente es un buen lugar), puede hacer una llamada como la siguiente:Vea el ciclo de vida de Fragment para decidir dónde configurar mejor el oyente en su implementación individual.
Este es un enfoque general para proporcionar una solución sólida y completa al problema genérico formulado en esta pregunta. Probablemente falten algunas piezas menores en esta respuesta dependiendo de su escenario individual, pero este es generalmente el enfoque más correcto para manejar adecuadamente los eventos de cambio de orientación.
fuente
He encontrado una solución más fácil para manejar hilos cuando cambia la orientación. Puede mantener una referencia estática a su actividad / fragmento y verificar si es nulo antes de actuar en la interfaz de usuario. Sugiero usar un try catch también:
fuente
Si tiene problemas para detectar los eventos de cambio de orientación de un diálogo INDEPENDIENTE DE UNA REFERENCIA DE ACTIVIDAD , este método funciona de manera emocionante. Lo uso porque tengo mi propia clase de diálogo que se puede mostrar en varias actividades diferentes, por lo que no siempre sé en qué actividad se muestra. Con este método no es necesario cambiar el manifiesto de Android, preocuparse por las referencias de actividad, y no necesitas un diálogo personalizado (como yo tengo). Sin embargo, necesita una vista de contenido personalizada para poder detectar los cambios de orientación utilizando esa vista en particular. Aquí está mi ejemplo:
Preparar
Implementación 1 - Diálogo
Implementación 2 - AlertDialog.Builder
Implementación 3 - ProgressDialog / AlertDialog
fuente
Esta es mi solución cuando lo enfrenté:
ProgressDialog
no es unFragment
niño, por lo que mi clase personalizada "ProgressDialogFragment
" puede extenderseDialogFragment
en su lugar para mantener el cuadro de diálogo que se muestra para los cambios de configuración.Hay 2 enfoques para resolver esto:
Primer enfoque: realice la actividad que utiliza el diálogo para retener el estado durante el cambio de configuración en el archivo de manifiesto:
Google no prefiere este enfoque.
Segundo enfoque: en el
onCreate()
método de la actividad , debe conservarloDialogFragment
reconstruyendoProgressDialogFragment
nuevamente con el título y el mensaje de la siguiente manera sisavedInstanceState
no es nulo:fuente
Parece demasiado 'rápido y sucio' para ser verdad, así que por favor señale los defectos, pero lo que encontré funcionó fue ...
Dentro del método onPostExecute de mi AsyncTask, simplemente envolví el '.dismiss' para el diálogo de progreso en un bloque try / catch (con un catch vacío) y luego simplemente ignoré la excepción que se generó. Parece incorrecto pero parece que no hay efectos nocivos (al menos para lo que estoy haciendo posteriormente, que es comenzar otra actividad pasando el resultado de mi consulta de larga duración como Extra)
fuente
Activity
tiene una referencia alDialog
. Cuando se cambia la configuración,Activity
se destruye el primero , lo que significa que todos los campos están configurados ennull
. Pero el nivel bajoWindowManager
también tiene una referencia alDialog
(ya que aún no se ha descartado). El nuevoActivity
intenta crear un nuevoDialog
(inpreExecute()
) y el administrador de ventanas genera una excepción fatal que le impide hacerlo. De hecho, si lo hace, no habría forma de destruir limpiamente elDialog
por lo tanto manteniendo una referencia a la inicialActivity
. Estoy en lo cierto?La solución más simple y flexible es utilizar una AsyncTask con una referencia estática a ProgressBar . Esto proporciona una solución encapsulada y, por lo tanto, reutilizable para los problemas de cambio de orientación. Esta solución me ha sido útil para diversas tareas asíncronas, incluidas las descargas de Internet, la comunicación con los Servicios y los análisis del sistema de archivos. La solución ha sido probada en múltiples versiones de Android y modelos de teléfonos. Puede encontrar una demostración completa aquí con interés específico en DownloadFile.java
Presento lo siguiente como un ejemplo conceptual
El uso en una actividad de Android es simple
fuente
Cuando cambia las orientaciones, Android elimina esa actividad y crea una nueva actividad. Sugiero usar retrofit con Rx java. cuyo mango se bloquea automáticamente.
Utilice este método cuando reequipa la llamada.
.subscribeOn (Schedulers.io ()) .observeOn (AndroidSchedulers.mainThread ())
fuente