java - startactivity - Modo de inicio Android "single top" y método onNewIntent
putextra android (3)
¿ onDestroy()
si onDestroy()
se llamó? Esa es probablemente la razón por la que onCreate()
se invoca cada vez en lugar de onNewIntent()
, que solo se onNewIntent()
si la actividad ya existe.
Por ejemplo, si abandona su actividad mediante el botón ATRÁS, se destruye de manera predeterminada. Pero si ArtistActivity.class
más en la pila de actividades hacia otras actividades y desde allí llamas a tu ArtistActivity.class
otra vez, omitirá onCreate()
y irá directamente a onNewIntent()
, porque la actividad ya ha sido creada y desde que la singleTop
como singleTop
Android no creará una nueva instancia de la misma, sino que tomará la que ya existe.
Lo que hago para ver qué está sucediendo Implemento funciones ficticias para todos los diferentes estados de cada actividad, así que siempre lo que está sucediendo ahora:
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
}
Lo mismo para onRestart()
, onStart()
, onResume()
, onPause()
, onDestroy()
Si lo anterior (botón ATRÁS) no era su problema, la implementación de estos maniquíes al menos le ayudará a depurarlo un poco mejor.
Leí en la documentación de Android que al establecer la propiedad launchMode de mi Actividad en singleTop O al agregar el indicador FLAG_ACTIVITY_SINGLE_TOP
a mi Intención, esa invocación de startActivity(intent)
reutilizaría una única instancia de Activity y me daría el Intent en la onNewIntent
llamada onNewIntent
. Hice ambas cosas, y onNewIntent
nunca dispara y onCreate
cada vez. Los documentos también dicen que this.getIntent()
devuelve el intento que primero pasó a la Actividad cuando se creó por primera vez. En onCreate
llamo a getIntent
y cada vez me getIntent
uno nuevo (estoy creando el objeto de intención en otra actividad y agregando un extra a él ... este extra debería ser el mismo siempre que me devolviera) el mismo objeto de intención). Todo esto me lleva a creer que mi actividad no está actuando como un "techo único", y no entiendo por qué.
Para agregar algunos antecedentes en caso de que simplemente me falta un paso obligatorio, aquí está mi declaración de actividad en el manifiesto y el código que estoy utilizando para iniciar la actividad. La actividad en sí no hace nada que valga la pena mencionar en relación con esto:
en AndroidManifest.xml:
<activity
android:name=".ArtistActivity"
android:label="Artist"
android:launchMode="singleTop">
</activity>
en mi actividad de llamada:
Intent i = new Intent();
i.putExtra(EXTRA_KEY_ARTIST, id);
i.setClass(this, ArtistActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
Establezca esta bandera según su intención:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
La respuesta aceptada no es del todo correcta. Si onDestroy () se llamó previamente, entonces sí, onCreate () siempre se llamará. Sin embargo, esta afirmación es incorrecta : "Si subes más en la pila de actividades hacia otras actividades y desde allí llamas a tu clase ArtistActivity.class, omitirá onCreate () e irá directamente a onNewIntent ()"
La sección "singleTop" de http://developer.android.com/guide/components/tasks-and-back-stack.html explica claramente cómo funciona (atención al texto en negrita a continuación; también he probado esto a través del mío) depuración):
"Por ejemplo, supongamos que la pila posterior de una tarea consiste en la actividad raíz A con las actividades B, C y D en la parte superior ( la pila es ABCD; D está en la parte superior ). Llega un intento para una actividad de tipo D. Si D tiene la modo de inicio predeterminado "estándar", se lanza una nueva instancia de la clase y la pila se convierte en ABCDD. Sin embargo, si el modo de lanzamiento de D''es "singleTop", la instancia existente de D recibe el intento a través deNewIntent (), porque está en la parte superior de la pila: la pila permanece ABCD. Sin embargo, si llega una intención para una actividad de tipo B, se agrega una nueva instancia de B a la pila, incluso si su modo de lanzamiento es "singleTop".
En otras palabras, comenzar una actividad a través de SINGLE_TOP solo reutilizará la actividad existente si ya está en la parte superior de la pila . No funcionará si hay otra actividad en esa misma tarea en la parte superior (por ejemplo, la actividad que está ejecutando startActivity (SINGLE_TOP)); se creará una nueva instancia en su lugar.
Aquí hay dos formas de corregir esto para que pueda obtener el comportamiento SINGLE_TOP que desea, cuyo objetivo general es reutilizar una actividad existente, en lugar de crear una nueva ...
Primera forma (como se describe en la sección de comentarios de la respuesta aceptada): puede agregar un launchMode de "singleTask" a su actividad. Esto forzaría onNewIntent () porque singleTask significa que solo puede haber UNA instancia de una actividad particular en una tarea determinada. Sin embargo, esta es una solución bastante hacky porque si su aplicación necesita varias instancias de esa actividad en una situación particular (como lo hago para mi proyecto), está jodido.
Segunda forma (mejor): en lugar de FLAG_ACTIVITY_SINGLE_TOP, usa FLAG_ACTIVITY_REORDER_TO_FRONT. Esto reutilizará la instancia de actividad existente moviéndola a la parte superior de la pila (se llamará a onNewIntent () como se esperaba).
El objetivo principal de FLAG_ACTIVITY_SINGLE_TOP es evitar la creación de instancias múltiples de una actividad. Por ejemplo, cuando esa actividad se puede iniciar a través de un intento que proviene de fuera de la tarea principal de la aplicación. Para el cambio interno entre actividades en mi aplicación, he encontrado que FLAG_ACTIVITY_REORDER_TO_FRONT es generalmente lo que quiero en su lugar.