Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Se está destruyendo la actividad porque la orientación ha cambiado o porque la aplicación se está cerrando?

Tengo una actividad que comienza un AsyncTask . La actividad se permite mostrar en orientación vertical u horizontal. Cuando se cambia la orientación, la Actividad se destruye y se vuelve a crear. La tarea continúa funcionando sin importar cuántas veces se cambie la orientación. También devuelve los resultados a la actividad con éxito (según la respuesta de CommonsWare aquí http://goo.gl/WF1yW ).

Lo que quiero lograr es: cuando la actividad se destruye porque la aplicación se está cerrando – la tarea debe ser cancelada. Sin embargo, cuando la actividad se destruye debido a un cambio de orientación – la tarea NO debe ser cancelada.

Básicamente la cuestión es cómo distinguir entre los dos casos: la aplicación es el cambio de cierre / orientación. En ambos casos se llama al método onDestroy () y no hay manera fácil de comprobar algo como isChangingOrientation () …

PS También puedo considerar un enfoque totalmente diferente si es necesario.

  • OnPostExecute no se llama después de la finalización AsyncTask
  • ¿Debo llamar a super () al sustituir el constructor de AsyncTask?
  • Async / espera no reaccionar como se esperaba
  • Android ¿cuántos hilos puedo tener?
  • Android, ¿puedo poner AsyncTask en una clase separada y tener una devolución de llamada?
  • Programar tareas asíncronas múltiples en android
  • Búsqueda automática como tipos de usuario
  • Android AsyncTask no se detendrá cuando se cancela, ¿por qué?
  • 6 Solutions collect form web for “¿Se está destruyendo la actividad porque la orientación ha cambiado o porque la aplicación se está cerrando?”

    En general, no desea definir onConfigurationChanged () porque es tan difícil hacer todo bien. El mejor enfoque es dejar que la aplicación sea asesinada y recreada cuando cambia la orientación.

    Para facilitar la transición, puede implementar onRetainNonConfigurationInstance () . Este método será llamado por el sistema cuando sepa que su aplicación se reiniciará casi inmediatamente. En onRetainNonConfigurationInstance () , pasas cualquier objeto arbitrario al sistema ('this' es una opción razonable). A continuación, en su método onCreate() , llama a getLastNonConfigurationInstance () para obtener el objeto previamente guardado. Esto le permite restaurar su estado de forma rápida y fácil desde la invocación anterior. Creo que incluso los subprocesos corrientes y los sockets abiertos pueden pasar por este camino.

    Consulte Guardar caché cuando gire el dispositivo para obtener más información.

    He encontrado una solución algo satisfactoria, que quiero compartir.

    El método onRetainNonConfigurationInstance () se llama sólo cuando se está recreando la actividad. Más específicamente: Called by the system, as part of destroying an activity due to a configuration change, when it is known that a new instance will immediately be created for the new configuration.

    Anular este método y almacenar un indicador (indicando si se ha llamado o no). Luego, en onDestroy (llamado poco después), compruebo esta bandera y si es falsa cancelo la tarea de fondo, porque la Actividad está siendo destruida para siempre. Si es verdad esto significa que onRetainNonConfigurationInstance () ha sido llamado, lo que significa que la actividad se está recreando, así que dejo la tarea en ejecución.

    Me hubiera gustado una solución mejor, pero no podría encontrar tal. Los problemas con esta solución son dos: el método está obsoleto ; No hay garantía de que el método será llamado (según la documentación). En la práctica la solución funciona para mí, así que voy a usarlo …

    Puede usar el método isFinishing() para comprobar si la actividad se va a matar o el método onDestroy() acaba de llamarse debido al cambio de orientación

     @Override protected void onDestroy() { super.onDestroy(); if(isFinishing()){ Log.i("DEBUG", "App will Terminate "); }else{ Log.i("DEBUG", "Orientation changed"); } } 

    Echa un vistazo aquí para una mejor comprensión del ciclo de vida de Android: http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

    Puede utilizar onConfigurationChanged () para detectar cambios de orientación en su actividad. Puede utilizar el método onDestroy () para determinar cuándo se va a matar su actividad.

    La mejor manera que encontré después de una investigación fue crear una clase de aplicación y confiar en el método onTrimMemory (). Un problema con este enfoque – onTrimMemory () no se llama si la pantalla se agota o se bloquea la pantalla pulsando el botón de encendido, así que tuve que implementar esa lógica por separado.

     /** * When your app's process resides in the background LRU list: * TRIM_MEMORY_BACKGROUND * TRIM_MEMORY_MODERATE * TRIM_MEMORY_COMPLETE * * When your app's visibility changes: * TRIM_MEMORY_UI_HIDDEN */ @Override public void onTrimMemory(final int level) { super.onTrimMemory(level); if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN || level == ComponentCallbacks2.TRIM_MEMORY_BACKGROUND || level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE || level == ComponentCallbacks2.TRIM_MEMORY_MODERATE) { // App went in background } } 

    El código siguiente es detectar el bloqueo de pantalla. Implementé este código en uno de los métodos ActivityLifecycleCallbacks – onActivityStopped ()

     final PowerManager powerManager = (PowerManager) getAppContext().getSystemService(Context.POWER_SERVICE); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { if (!powerManager.isScreenOn()) { // Screen locked } } else { if (!powerManager.isInteractive()) { // Screen locked } } 

    Si su aplicación se orienta al nivel API 13 o superior, debe establecer esta configuración en el archivo manifest.xml

     <activity android:configChanges="orientation|screenSize" ... /> 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.