Android: Effacer la pile d'activités

132

J'ai plusieurs activités dans mon application. et le flux est très compliqué. Lorsque je clique, l'application de déconnexion accède à l'écran de connexion et à partir de là, l'utilisateur peut quitter en cliquant sur le bouton d'annulation (appelant system.exit(0))

lorsque je quitte ou que je retourne, le système appelle une activité de la pile: (comment puis-je effacer toutes les activités de la pile lorsque j'atteins l'écran de connexion? L'appel finish()n'est pas pratique car il y a tellement d'activités et certaines activités ne devraient pas être fermées quand ils sont actifs comme une caméra native invoquant une activité.

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
la source

Réponses:

339

La plupart d'entre vous ont tort. Si vous souhaitez fermer la pile d'activités existante indépendamment de ce qui s'y trouve et créer une nouvelle racine, le jeu d'indicateurs correct est le suivant:

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

Du doc :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Ajouté au niveau d'API 11

S'il est défini dans une intention transmise à Context.startActivity(), cet indicateur entraînera l'effacement de toute tâche existante qui serait associée à l'activité avant le démarrage de l'activité. Autrement dit, l'activité devient la nouvelle racine d'une tâche autrement vide, et toutes les anciennes activités sont terminées. Cela ne peut être utilisé qu'avec FLAG_ACTIVITY_NEW_TASK.

Cynichniy Bandera
la source
A parfaitement fonctionné. Merci. Étrangement, n'a pas donné d'erreur avec minSDK = 9.
Mahm00d
Franchement, je n'ai jamais utilisé cette fonctionnalité, ressuscité après un crash, etc., et plutôt concentré sur la
résolution
La même fonctionnalité fournit également à IntentCompat.makeRestartActivityTaskpartir de la bibliothèque de support.
sealskej
L'ajout de seulement ces deux indicateurs laisse la trace de la pile d'activité derrière (commence par-dessus le précédent), puis a ajouté Intent.FLAG_ACTIVITY_CLEAR_TOP qui redémarre simplement l'application puis se ferme totalement. Je n'ai ajouté aucun drapeau aux activités explicitement tho. Quel pourrait être le problème?
Farid
1
L'un des meilleurs débuts: «La plupart d'entre vous se trompent».
nibbana
31

Lorsque vous appelez startActivityla dernière activité, vous pouvez toujours utiliser

Intent.FLAG_ACTIVITY_CLEAR_TOP

comme indicateur de cette intention.

En savoir plus sur le drapeau ici .

David Olsson
la source
cela n'aide pas non plus. Je viens d'évoquer une activité dat ne se terminant pas par finish (); :(
Jay Mayu
Je suppose que FLAG_ACTIVITY_CLEAR_TOP efface les activités en haut. Mon problème est les activités en bas :(
Jay Mayu
Je suppose que cela dépend de la façon dont le flux est réellement. Vous devriez en savoir plus ici: developer.android.com/reference/android/content/… et developer.android.com/guide/topics/fundamentals/…
David Olsson
7
Merci de montrer les bonnes ressources. l'erreur que j'ai faite a été de fermer l'activité de connexion. Je ne devrais pas le fermer. Lorsque l'activité s'est chargée en premier. Ainsi, lorsque je le rappelle en utilisant l'indicateur Clear_top, l'activité de connexion efface toutes les activités en haut. comme la connexion est la première activité d'entrée, elle efface toutes les activités commencées après. alors le bingo a fonctionné :)
Jay Mayu
13
D'après la documentation, FLAG_ACTIVITY_CLEAR_TOP efface la pile uniquement si l'activité spécifique "déjà en cours d'exécution dans la tâche en cours"
AlikElzin-kilaka
16

Voici une méthode d'aide simple pour démarrer une nouvelle activité en tant que nouvelle activité principale qui fonctionne du niveau d'API 4 jusqu'à la version actuelle 17:

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);
}

appelez-le comme ceci à partir de votre activité actuelle:

startNewMainActivity(this, MainActivity.class);
whlk
la source
1
Ne pourriez-vous pas toujours utiliser intent.addFlags (0x8000); et simplifier cela?
Davor
Comme cet indicateur a été introduit pour la première fois dans Honeycomb, je n'ai aucune idée de son implication sur les versions antérieures. Donc, c'était moi qui faisais des précaucios. Mais je suppose que la suppression du conditiel ne devrait pas être un problème.
whlk
1
vous voulez ajouter cet indicateur lorsque le niveau d'API est <11, vous devez faire Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBautrement ne intent.addFlags(0x8000);sera jamais ajouté
Chapeau de paille
Je demande à l'utilisateur de faire de nombreuses activités les unes après les autres à travers des intentions. Dois-je faire quelque chose pour m'assurer que l'application ne plante pas avec trop d'activités sur la pile? Merci!
Ruchir Baronia
9

Effacez le backstate d'activité par le code ci-dessous:

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);

Terminé

Hiren Patel
la source
Je demande à l'utilisateur de faire de nombreuses activités les unes après les autres à travers des intentions. Dois-je faire quelque chose pour m'assurer que l'application ne plante pas avec trop d'activités sur la pile? Merci!
Ruchir Baronia
@RuchirBaronia, Si vous allez A -> B -> C -> D -> E -> F -> G -> H, maintenant H -> Je vous écris mon code que je serai Dernière activité après avoir appuyé sur le bouton Retour l'application se fermera car l'application n'a pas d'activité dans l'arrière-pays, j'espère que cela vous aidera.
Hiren Patel du
Dois-je le faire cependant? Que se passera-t-il si je ne nettoie jamais la pile d'activités?
Ruchir Baronia
@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
Hiren Patel
Mais un certain temps, il affiche un écran blanc tout en appelant une nouvelle activité. Ho pour résoudre ça?
Sagar
4

Dans mon cas, LoginActivity a également été fermé. Par conséquent,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

n'a pas aidé.

Cependant, le réglage

Intent.FLAG_ACTIVITY_NEW_TASK

m'a aidé.

Prashant Gami
la source
Je demande à l'utilisateur de faire de nombreuses activités les unes après les autres à travers des intentions. Dois-je faire quelque chose pour m'assurer que l'application ne plante pas avec trop d'activités sur la pile? Merci!
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
la source
1
pourquoi vous utilisez les deux this.finish()et setFlags()aussi pour effacer l'activité actuelle?
Sagar
3

J'ai noté que vous avez demandé une solution qui ne repose pas sur finish() , mais je me demande si cela peut néanmoins aider.

J'ai suivi si un indicateur de sortie est déclenché avec une variable de classe statique, qui survit à toute la durée de vie de l'application. Dans chaque activité pertinenteonResume() , utilisez

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

La classe ExitHelper

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

Disons que dans mainActivity, un utilisateur appuie sur un bouton pour quitter - vous pouvez définir ExitHelper.isExitFlagRaised = true;et ensuite finish(). Par la suite, d'autres activités pertinentes qui reprendront automatiquement seront également terminées.

Kevin Lee
la source
que se passera-t-il si j'utilise le code dans MainActivity onresume () puis reviens à l'activité principale à partir de la 2ème activité onbackpress
Mithu
3

Cette décision fonctionne bien:

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

Mais la nouvelle activité se lance longtemps et vous voyez un écran blanc un certain temps. Si cela est critique, utilisez cette solution de contournement:

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();
    }
}

Comment l'utiliser:

public class ActivityA extends BaseActivity {

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

Inconvénient: toutes les activités qui doivent être fermées sur la pile doivent étendre BaseActivity

maXp
la source
2

Pour les développeurs Xamarin, vous pouvez utiliser:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
BYISHIMO Audace
la source
1

Utilisation de Kotlin:

Vous pouvez définir le drapeau directement en utilisant la méthode setter. Dans Kotlin orest le remplacement de Java bitwise ou |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Si vous prévoyez de l'utiliser régulièrement, créez une fonction d'extension d'intention

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

Vous pouvez ensuite appeler directement cette fonction avant de démarrer l'intention

intent.clearStack()
Gibolt
la source