Cómo terminar la actividad destruida
Según entiendo, una actividad destruida no es equivalente a una actividad que está terminando .
- Terminado
- La actividad se quita de la pila trasera .
- Puede ser activado por el programa (por ejemplo, llamando a
finish()
), o por el usuario pulsando la tecla back (que implícitamente llama afinish()
). - Terminar una actividad lo destruirá.
- Destruido
- El sistema operativo Android puede destruir una actividad invisible para recuperar la memoria. La actividad se recreará cuando el usuario vuelva a ella.
- La actividad se destruye y se vuelve a crear cuando el usuario gira la pantalla.
- Referencia: recreando una actividad
Entonces, ¿ cómo puedo terminar una actividad destruida ? El método finish()
requiere un objeto Activity
, pero si la actividad se destruye, no tengo ningún objeto Activity
– no se supone que debo mantener una referencia a una actividad destruida, ¿verdad?
- Android: Ir al URL de HTTP en el botón de clic
- Android No se puede instanciar la actividad: No encontró la clase en el path
- Android: ¿Por qué se llama onTabSelected cuando se crean pestañas?
- Desacoplamiento de la aplicación en la aplicación de la actividad
- Iniciar IntentService de Actividad y actualizar Actividad cuando IntentService finaliza
Caso de estudio:
Tengo una actividad a
, que comienza b
, que a su vez comienza c
(usando Activity.startActivity()
), así que ahora la pila trasera es:
a → b → c
En c
, el usuario rellena un formulario y presiona el botón Enviar. Se realiza una solicitud de red a un servidor remoto mediante AsyncTask
. Después de completar la tarea, muestro un brindis y termino la actividad llamando a c.finish()
. Perfecto.
Ahora considere este escenario:
Mientras la tarea asíncrona está en progreso, el usuario cambia a otra aplicación. Luego, el sistema operativo Android decidió destruir las 3 actividades ( a
, b
, c
) debido a las restricciones de memoria. Posteriormente, se completa la tarea asíncrona. Ahora, ¿cómo terminar c
?
Lo que he intentado:
- Llamar a
c.finish()
:- No se puede, porque
c
se destruye.
- No se puede, porque
- Llamar
b.finishActivity()
:- No se puede, porque
b
es destruido.
- No se puede, porque
-
Utilice
Context.startActivity()
conFLAG_ACTIVITY_CLEAR_TOP
para elevarb
a la parte superior, finalizando asíc
:// appContext is an application context, not an activity context (which I don't have) Intent intent = new Intent(appContext, B.class); // B is b's class. intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); appContext.startActivity(intent);
- Error,
appContext.startActivity()
lanza una excepción:
- Error,
Android.util.AndroidRuntimeException: Llamar startActivity () desde fuera de un contexto de Activity requiere el flag FLAG_ACTIVITY_NEW_TASK. ¿Es esto realmente lo que quieres?
Edición: Aclaración: Tengo que esperar hasta que termine la tarea asíncrona y decidir si terminar c
basado en la respuesta del servidor.
- ¿Cómo escuchar los cambios de preferencia dentro de un archivo PreferenceFragment?
- Datos que pasan a otra aplicación en Android
- SharedPrefs se restablece después de configurar la configuración regional de la aplicación de Android
- Muestra de ventana incorrecta, no se puede mostrar un diálogo antes de que se cree una actividad o después de que esté oculta
- Actividad de cierre de Android mediante programación
- Mover una imagen en una ruta circular en android
- Configuración de HAXM en el android studio
- Entendimiento de MvxCachingFragmentCompatActivity
Android.util.AndroidRuntimeException: Llamar startActivity () desde fuera de un contexto de Activity requiere el flag FLAG_ACTIVITY_NEW_TASK. ¿Es esto realmente lo que quieres?
-
Esta excepción solía ocurrir cuando se inicia una actividad desde
El hilo o servicio de fondo. Necesitas pasar
FLAG_ACTIVITY_NEW_TASK bandera siempre que necesite el "lanzador"
Tipo de comportamiento.- Simplemente agregue
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Para evitar esta excepción.
- Simplemente agregue
- La forma en que está tratando de matar a la actividad no es recomendable, que el android manejar por sí mismo. No hay ningún significado para terminar una actividad que ya está destruida.
Ahora, ¿qué puedes hacer?
-
Si se enfrenta a un problema en la actividad de acabado cuando la aplicación no está en primer plano, lo que puede hacer es implementar una comprobación de seguridad que finalizará la actividad sólo cuando la aplicación esté en primer plano para ir a la actividad de back-stack o simplemente saltar ese paso.
-
Pienso que usted está intentando matar la actividad cuando la aplicación está en fondo. Parece un poco difícil hacerlo, pero puedes hacer uso de onUserLeaveHint para decidir cuando la aplicación va en segundo plano en orden para terminar la actividad o puedes terminar la actividad agregando
finish();
EnonStop()
. Sólo asegúrese de que asynctask'sonPost()
no lo termine de nuevo en orden para evitar la excepción. -
Echa un vistazo a android: clearTaskOnLaunch atributo y establecerlo en true.
Google Doc dice sobre este atributo es:
Por ejemplo, que alguien inicie la actividad P desde la pantalla de inicio y de ahí va a la actividad Q. El usuario presiona a continuación en Inicio y luego vuelve a la actividad P. Normalmente, el usuario vería la actividad Q, ya que es lo que fueron últimos Haciendo en la tarea de P. Sin embargo, si P estableció este indicador como "true", todas las actividades encima de él (Q en este caso) fueron eliminadas cuando el usuario pulsó Home y la tarea fue al fondo. Por lo tanto, el usuario sólo ve P al volver a la tarea.
Y creo que este es el caso exacto que desea.
Espero que esto le dará alguna pista para lograr su tarea deseada.
Puede transmitir su acción desde el método onPostExecute
en c y registrar un receiver
difusión para recibir para esa acción en a y b. A continuación, terminar en ese método de receptor onRevice
En c
, AsyncTask,
void onPostExecute(Long result) { ---- Intent intent1 = new Intent("you custom action"); context.sendBroadcast(intent1); }
En a
y b
registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { finish(); } },new IntentFilter("you custom action"));
Personalmente, usaría la barra de notificación para notificar al usuario del estado de su consulta.
De esta manera, evitaría toda la cuestión de tener una actividad inacabada. Y sólo mantendría la actividad inacabada sólo si el usuario no había hecho clic en el botón de envío todavía.
En cuanto a android manual onDestroy()
llamado exactamente antes de la actividad se destruye, por lo que puede llamar a terminar en ella (incluso puede detener su hilo bg antes de matar la actividad completamente).
Podemos asumir que si la actividad fue asesinada no nos interesa bg thread tampoco, y por ejemplo, si bg hilo es descargar imagen o etc que necesita ser completado – por lo que tiene que utilizar el servicio en lugar de asynctask.
No se puede terminar una actividad destruida directamente, por lo que acaba de finish()
en su onCreate()
(sugerido por @Labeeb P ). Así es cómo:
-
Si la actividad ya está destruida al intentar terminarla, guarde una bandera booleana en algún lugar.
if(activity != null) { // Activity object still valid, so finish() now. activity.finish(); } else { // Activity is destroyed, so save a flag. is_activity_pending_finish = true; }
- Si la bandera necesita permanecer incluso si la aplicación se destruye, utilice almacenamiento persistente, por ejemplo
SharedPreferences
(sugerido por @Labeeb P ).
- Si la bandera necesita permanecer incluso si la aplicación se destruye, utilice almacenamiento persistente, por ejemplo
-
En
onCreate()
la actividad, compruebe el flag y callfinish()
.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(is_activity_pending_finish) { is_activity_pending_finish = false; // Clear the flag. // This activity should have been finished, so finish it now. finish(); return; } ... }
- Si hay varias instancias de la misma clase de actividad, es posible que necesite algo más que un indicador booleano para identificar la instancia específica de actividad para finalizar.
Llamar finish()
en onCreate()
es en realidad una operación legimate, como se menciona en el doc :
… puede llamar
finish()
desdeonCreate()
para destruir la actividad. En este caso, el sistema invoca de inmediatoonDestroy()
sin llamar a ninguno de los otros métodos de ciclo de vida.
Otras Consideraciones:
- Puede que no sea una buena idea terminar una actividad mientras la aplicación esté en segundo plano, especialmente si es la única actividad. Asegúrese de no confundir al usuario.
- Para obtener una mejor experiencia del usuario, si termina una actividad mientras la aplicación está en segundo plano, quizás desee informar al usuario. Considere el uso de tostadas (bueno para avisos cortos) o notificaciones (buenas para operaciones largas que el usuario puede haber olvidado) (sugeridas por @Stephan Branczyk y @dilix ).
Por supuesto, una actividad destruida no significa necesariamente que la aplicación esté en segundo plano (podría haber otra actividad de primer plano). Sin embargo, la solución anterior (llamar finish()
en onCreate()
) funciona.
Cuando el sistema intenta destruir su actividad, llama a onSaveInstanceState
. Aquí puede llamar a finish()
. Eso es.
Advertencia: Nunca he probado esto, así que no sé a ciencia cierta si hay problemas con la llamada finish () de onSaveInstanceState. Si intenta esto, por favor, comente y hágamelo saber cómo funciona.
- COCOS 2D captura de pantalla es negro en Android
- La textura transparente de Android OpenGL dibuja negro