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);
Jay Mayu
fuente
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.

Cynichniy Bandera
fuente
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í .

David Olsson
fuente
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);
whlk
fuente
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

Hiren Patel
fuente
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ó.

Prashant Gami
fuente
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();
Sakib Syed
fuente
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.

Kevin Lee
fuente
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

maXp
fuente
2

Para los desarrolladores de Xamarin, puede usar:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
BYISHIMO Audace
fuente
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()
Gibolt
fuente