Android: Clear Activity Stack


132

Estoy teniendo varias actividades en mi aplicación. y el flujo es muy complicado. Cuando hago clic en la aplicación Cerrar sesión, navega a la pantalla de inicio de sesión y desde allí el usuario puede salir presionando el botón cancelar (llamando system.exit(0))

cuando salgo o retrocedo, el sistema invoca una actividad de la pila :( ¿cómo puedo borrar todas las actividades en la pila cuando llego a la pantalla de inicio de sesión? llamar finish()no es práctico ya que hay tantas actividades y algunas actividades no deberían cerrarse cuando están activos, como la actividad de invocación de cámara nativa.

validateuser logoutuser = new validateuser();
logoutuser.logOut();
Intent loginscreen = new Intent(homepage.this, Login2.class);
(homepage.this).finish();
loginscreen.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(loginscreen);

1
mira

Posible duplicado de Android:
borra la

Respuestas:


339

La mayoría de ustedes está equivocado. Si desea cerrar la pila de actividades existente independientemente de lo que haya allí y crear una nueva raíz, el conjunto correcto de indicadores es el siguiente:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Desde el documento :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Agregado en API nivel 11

Si se establece en un Intento pasado Context.startActivity(), este indicador hará que cualquier tarea existente que esté asociada con la actividad se borre antes de que se inicie la actividad. Es decir, la actividad se convierte en la nueva raíz de una tarea que de otro modo estaría vacía, y las actividades antiguas se completan. Esto solo se puede usar junto con FLAG_ACTIVITY_NEW_TASK.


Funcionó perfectamente. Gracias. Extrañamente no dio error con minSDK = 9.
Mahm00d

Francamente, nunca utilicé esta funcionalidad, resucité después del accidente, etc., y me concentré en solucionar los problemas que causaron el bloqueo)
Cynichniy Bandera

La misma funcionalidad también proporciona IntentCompat.makeRestartActivityTaskde la biblioteca de soporte.
sealskej

Agregar solo esas dos banderas deja atrás el seguimiento de la pila de actividad (comienza en la parte superior de la anterior), luego agrega Intent.FLAG_ACTIVITY_CLEAR_TOP que simplemente reinicia la aplicación y luego se cierra por completo. No he agregado ninguna bandera a las actividades explícitamente. ¿Cual podría ser el problema?
Farid

1
Uno de los mejores comienzos: "La mayoría de ustedes están equivocados".
nibbana

31

Cuando llamas startActivitya la última actividad, siempre puedes usar

Intent.FLAG_ACTIVITY_CLEAR_TOP

como una bandera en ese intento.

Lea más sobre la bandera aquí .


eso tampoco ayuda. Acabo de mencionar una actividad que no termina con finish (); :(
Jay Mayu

Supongo que FLAG_ACTIVITY_CLEAR_TOP borra las actividades en la parte superior. Mi problema son las actividades en la parte inferior :(
Jay Mayu

Supongo que depende de cómo sea realmente el flujo. Debería leer más sobre esto aquí: developer.android.com/reference/android/content/… y developer.android.com/guide/topics/fundamentals/…
David Olsson

77
Gracias por mostrar los recursos correctos. El error que hice fue cerrar la actividad de inicio de sesión. No debería cerrarlo. Cuando la actividad se cargó primero. así que cuando vuelvo a llamar usando el indicador Clear_top, la actividad de inicio de sesión borra todas las actividades en la parte superior. Como el inicio de sesión es la primera actividad de entrada, borra todas las actividades que se inician después. así que el bingo funcionó :)
Jay Mayu

13
De la documentación, FLAG_ACTIVITY_CLEAR_TOP borra la pila solo si la actividad específica "ya se está ejecutando en la tarea actual"
AlikElzin-kilaka

16

Aquí hay un método auxiliar simple para comenzar una nueva actividad como la nueva actividad principal que funciona desde el nivel 4 de API hasta la versión 17 actual:

static void startNewMainActivity(Activity currentActivity, Class<? extends Activity> newTopActivityClass) {
    Intent intent = new Intent(currentActivity, newTopActivityClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
    currentActivity.startActivity(intent);
}

llámalo así desde tu actividad actual:

startNewMainActivity(this, MainActivity.class);

1
¿No podría simplemente usar intent.addFlags (0x8000); y simplificar eso?
Davor

Como esta bandera se introdujo por primera vez en Honeycomb, no tengo idea de qué implicación podría tener en versiones anteriores. Entonces, este era yo siendo precaucios. Pero supongo que la eliminación del conditial no debería ser un problema.
whlk

1
desea agregar esa bandera cuando el nivel de API es <11, entonces debe hacer Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBotra cosa intent.addFlags(0x8000);que nunca se agregará
Straw Hat

Estoy haciendo que el usuario realice muchas actividades una tras otra a través de intentos. ¿Debo hacer algo para asegurarme de que la aplicación no se bloquee con demasiadas actividades en la pila? ¡Gracias!
Ruchir Baronia

9

Borrar Actividad Backstate con el siguiente código:

Intent intent = new Intent(Your_Current_Activity.this, Your_Destination_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Hecho


Estoy haciendo que el usuario realice muchas actividades una tras otra a través de intentos. ¿Debo hacer algo para asegurarme de que la aplicación no se bloquee con demasiadas actividades en la pila? ¡Gracias!
Ruchir Baronia

@RuchirBaronia, si vas A -> B -> C -> D -> E -> F -> G -> H, ahora H -> Escribo mi código de lo que seré Última actividad después de presionar el botón Atrás la aplicación se cerrará porque no tiene actividad en el backstate, espero que esto te ayude.
Hiren Patel

¿Pero necesito hacer eso? ¿Qué pasará si nunca limpio la pila de actividades?
Ruchir Baronia

@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
Hiren Patel el

Pero en algún momento muestra una pantalla en blanco al llamar a una nueva actividad. ¿Cómo resolver esto?
Sagar

4

En mi caso, LoginActivity también se cerró. Como resultado,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

no ayudó.

Sin embargo, la configuración

Intent.FLAG_ACTIVITY_NEW_TASK

me ayudó.


Estoy haciendo que el usuario realice muchas actividades una tras otra a través de intentos. ¿Debo hacer algo para asegurarme de que la aplicación no se bloquee con demasiadas actividades en la pila? ¡Gracias!
Ruchir Baronia

3
Intent intent = new Intent(LoginActivity.this, Home.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  //It is use to finish current activity
startActivity(intent);
this.finish();

1
¿Por qué está utilizando ambos this.finish()y setFlags()también para borrar la actividad actual?
Sagar

3

Noté que solicitó una solución en la que no se basa finish(), pero me pregunto si esto puede ayudar de todos modos.

Rastreé si se levanta un indicador de salida con una variable de clase estática, que sobrevive a toda la vida útil de la aplicación. En cada actividad relevanteonResume() , use

@Override
public void onResume() {
    super.onResume();
    if (ExitHelper.isExitFlagRaised) {
        this.finish();
    }
}

La clase ExitHelper

public class ExitHelper {
    public static boolean isExitFlagRaised = false;
}

Digamos que en mainActivity, un usuario presiona un botón para salir; puede configurarlo ExitHelper.isExitFlagRaised = true;y luego finish(). A partir de entonces, también se terminarán otras actividades relevantes que se reanuden automáticamente.


lo que sucederá si uso el código en MainActivity onResume () y luego volver a mainactivity de segunda actividad onbackpress
Mithu

3

Esta decisión funciona bien:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Pero la nueva actividad se inicia por mucho tiempo y ves una pantalla en blanco en algún momento. Si esto es crítico, utilice esta solución alternativa:

public class BaseActivity extends AppCompatActivity {

    private static final String ACTION_FINISH = "action_finish";

    private BroadcastReceiver finisBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        registerReceiver(finisBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                finish();
            }
        }, new IntentFilter(ACTION_FINISH));
    }

    public void clearBackStack() {
        sendBroadcast(new Intent(ACTION_FINISH));
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(finisBroadcastReceiver);
        super.onDestroy();
    }
}

Cómo usarlo:

public class ActivityA extends BaseActivity {

    // Click any button
    public void startActivityB() {
        startActivity(new Intent(this, ActivityB.class));
        clearBackStack();
    }
}

Desventaja: todas las actividades que deben cerrarse en la pila deben extender BaseActivity


2

Para los desarrolladores de Xamarin, puede usar:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);

1

Usando Kotlin:

Puede establecer la bandera directamente utilizando el método setter. En Kotlin se orencuentra el reemplazo para Java o bit a bit |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Si planea usar esto regularmente, cree una función de extensión de intención

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Luego puede llamar directamente a esta función antes de comenzar la intención

intent.clearStack()
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.