Termina la actividad anterior y comienza una nueva o viceversa

80

Sé que obtengo el mismo resultado con ambos fragmentos de código

finish();
startActivity(newActivity);

y

startActivity(newActivity);
finish();

Me gustaría saber tu opinión, si hay una gran diferencia entre ellos. ¿Es uno mejor que el otro? Si es así, ¿por qué?

Tima
fuente

Respuestas:

61

Cuando inicia la actividad (), todo lo que hace es publicar su intención en una cola de eventos. El inicio real de la actividad ocurre de forma asincrónica en un futuro próximo. Entonces no veo una gran diferencia entre los dos.

Emmanuel
fuente
1
también me suena sensato
Tima
6
La animación es diferente para mí. Vea mi respuesta a continuación.
Monstieur
pero el enfoque es completamente INCORRECTO. Hay indicadores (para la intención y en el manifiesto) que realmente existen para estos casos de uso.
Ewoks
@Ewoks, por favor, vaya, ¿qué significa, qué banderas?
Anthony
3
En realidad, existe una gran diferencia en el comportamiento de las tareas de la aplicación. Elaboré el asunto en una respuesta separada.
Vit Khudenko
27

La animación es claramente diferente (al menos en 4.1 en adelante). Llamar finish()primero comienza a desvanecerse la primera actividad antes y puede ver brevemente un fondo negro antes de que la nueva actividad se desvanezca. Llamar startActivity()primero se desvanece en la nueva actividad encima de la anterior y el fondo negro no es visible.

Monstieur
fuente
16

Existe una diferencia importante en el comportamiento de las tareas de la aplicación según el orden startActivity()y las finish()invocaciones.

El caso que estoy describiendo tiene como alcance solo la situación en la que la actividad actual (la que se detiene) es la única en la tarea.

Normalmente, esperaría que el sistema no altere la intención inicial (la intención que crea para iniciar otra actividad). Y ese no es el caso si finish()se llama en la última actividad de la tarea antes de llamar startActivity().

En este caso, el ActivityManager, un componente del sistema, mientras ejecuta el indicador de startActivity() adiciones Intent.FLAG_ACTIVITY_NEW_TASK a su intención.

Cuando esto sucede, uno puede notar una entrada de registro en LogCat similar a esta:

W / ActivityManager: startActivity llamado desde finalizar ActivityRecord {4a19b47 u0 com.foo.bar/com.foo.bar.SplashActivity t4928 f}; forzando Intent.FLAG_ACTIVITY_NEW_TASK para: Intent {cmp = com.foo.bar / com.foo.bar.MainActivity}

Y este es el punto de inflexión a partir del cual (bajo algunas condiciones) las cosas pueden salir mal.

En resumen, si desea estar seguro (en lugar de experimentar efectos secundarios inesperados de que FLAG_ACTIVITY_NEW_TASKse agregue a la intención), entonces el orden debe ser:

  • startActivity()
  • finish()

Proyecto de demostración .

Grabaciones de pantalla:

Vit Khudenko
fuente
Al observar el código fuente, Activity.startActivity () finalmente llama a ActivityThread.sendActivityResult () que a su vez llama a scheduleSendResult () que simplemente agrega la actividad a una cola. Un hilo lo procesará más tarde. Por otro lado, finish () llama a ActivityManagerNative.finishActivity () que finaliza la actividad de inmediato.
Emmanuel
@Emmanuel, no entiendo si su declaración se relaciona con el problema que describí. :)
Vit Khudenko
9

Además de la respuesta de Emmanuels:

Ambos métodos startActivityy finishserán programadas después de la final del método de invocación, ya que ambos son procesados por el hilo de interfaz de usuario.

Scheffield
fuente
7

Haría la segunda opción, no estoy respaldando esto en nada que haya buscado en fuentes oficiales, pero tiene más sentido lanzar la nueva actividad antes de llamar a finalizar, de esa manera la nueva actividad aparece a través de una intención. , y la actividad ahora en segundo plano puede llamar a todos sus métodos de limpieza.

Si lo hiciera al revés, tal vez la intención no tenga tiempo de disparar antes de que se complete la limpieza. Es decir, ¿la actividad llamará a startActivity () después de la llamada finish ()?

Espero que entienda lo que estoy tratando de decir, haría la segunda opción solo para estar seguro.

ciego
fuente
Sí, entendí tu idea. Suena lógico. Pero no puedo imaginarme, cuando esta situación podría ser posible
Tima
2

Tuve un problema similar:

Activity A: singleInstance
Activity B: singleInstance
Activity C: singleInstance

A starts B 
B starts C
C wants to start A:

aquí si uso:

finish();
startActivity(A);

sucede algo cableado: ¡la actividad B pasa a primer plano en lugar de A! pero si cambio el código así:

startActivity(A);
finish();

todo parece estar bien y la Actividad A se hace visible.

No sé cuál es el problema, pero parece que en el primer caso, C finaliza antes de ejecutar el comando startActivity para que la pila de actividades maneje la situación y muestre su actividad principal, que es B! pero en el segundo caso, todo sucede con normalidad.

narges
fuente
Cuando termine () la aplicación, Android extrae la actividad LRU de la pila, que es B. Además, lo que me hace pensar que finish () es inmediato y no asincrónico.
Mehmet AVŞAR
0

Normalmente lo hago startActivity()antes, finish()ya que creo que eso aseguraría que la nueva pantalla salga antes de que se apague la anterior.

Tengo una página de inicio de sesión en mi aplicación. Una vez que el usuario inicia sesión correctamente, la actividad de inicio de sesión desaparece y la actividad principal está activa. Funciona bien en Android 4.

Hoy quería reescribirlo en Material design. Sin embargo, tengo un gran problema. El nuevo estudio de Android crea actividad en blanco con material design que creo que requiere muchos recursos. El mismo proceso, pero recibí el error.

11-26 18:20:44.450 18397-18397/? I/Choreographer: Skipped 42 frames!  The application may be doing too much work on its main thread.
11-26 18:20:44.485 18397-18408/? I/art: Background partial concurrent mark sweep GC freed 2864(191KB) AllocSpace objects, 4(43MB) LOS objects, 13% free, 100MB/116MB, paused 8.056ms total 39.767ms

Dijo que mis aplicaciones requieren muchos recursos cuando se mainActivityinicia en el registro de mi teléfono. No tengo nada mainActivitysolo que es el diseño de Material Design predeterminado.

Invertí el orden y ahora funciona sin errores en mi teléfono.

sombrero
fuente