Pregunta Modo de inicio Android "single top" y método onNewIntent


Leí en la documentación de Android que estableciendo la propiedad launchMode de mi actividad en singleTop o agregando el FLAG_ACTIVITY_SINGLE_TOP bandera a mi intención, esa vocación startActivity(intent) reutilizaría una sola instancia de actividad y me daría la intención en el onNewIntent llamar de vuelta. Hice ambas cosas, y onNewIntent nunca dispara y onCreate dispara todo el tiempo. 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 estoy llamando getIntent y estoy obteniendo uno nuevo cada vez (estoy creando el objeto intencional en otra actividad y agregando un extra a este ... este extra debería ser el mismo siempre si me devolviera el mismo objeto intencionado). 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);

41
2017-11-10 22:45


origen


Respuestas:


¿Marcó si onDestroy() fue llamado también? Esa es probablemente la razón por la cual onCreate() se invoca cada vez en lugar de onNewIntent(), que solo se llamaría si la actividad ya existe.

Por ejemplo, si abandona su actividad mediante el botón ATRÁS, se destruye de manera predeterminada. Pero si subes más en la pila de actividades en otras actividades y de allí llamas a tu ArtistActivity.class nuevamente se saltará onCreate() e ir directamente a onNewIntent(), porque la actividad ya se ha creado y desde que la definiste 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();
}

Igual por 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.


36
2017-11-11 14:12



La respuesta aceptada no es del todo correcta. Si onDestroy () se llamó previamente, entonces sí, onCreate () siempre se llamará. Sin embargo, esta declaración es incorrecta: "Si subes más en la pila de actividades en otras actividades y desde allí llamas a tu ArtistActivity.class otra vez, omitirá crear () 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 siguiente texto en negrita; también lo he comprobado a través de mi propia 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 A-B-C-D; D está arriba) Llega un intento para una actividad de tipo D. Si D tiene el modo de inicio "estándar" predeterminado, se inicia una nueva instancia de la clase y la pila se convierte en A-B-C-D-D. Sin embargo, si el modo de inicio de D's 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 sigue siendo A-B-C-D. Sin embargo, si llega un intento 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 es Ya 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 maneras de arreglar esto para que obtenga 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 los aceptados    respuesta): 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.


23
2017-09-18 23:33



Establezca esta bandera según su intención:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)

3
2017-08-25 01:20