web-dev-qa-db-fra.com

Efface toute la pile d'historique et commence une nouvelle activité sur Android

Est-il possible de démarrer une activité sur la pile en effaçant l'historique complet qui la précède?

La situation

J'ai une pile d'activités qui va soit A-> B-> C ou B-> C (l'écran A sélectionne le jeton des utilisateurs, mais de nombreux utilisateurs n'ont qu'un seul jeton). 

Dans l'écran C, l'utilisateur peut entreprendre une action qui rend l'écran B invalide. Par conséquent, l'application souhaite les amener à l'écran A, qu'il soit déjà dans la pile. L'écran A devrait alors être le seul élément de la pile dans mon application.

Remarques

Il y a beaucoup d'autres questions similaires, mais je n'ai rien trouvé qui réponde à cette question précise. J'ai essayé d'appeler getParent().finish() - il en résulte toujours une exception de pointeur null. FLAG_ACTIVITY_CLEAR_TOP ne fonctionne que si l'activité est déjà sur la pile. 

288
Casebash

Dans l'API de niveau 11, un nouvel indicateur d'intention a été ajouté uniquement pour cela: Intent.FLAG_ACTIVITY_CLEAR_TASK

Juste pour clarifier, utilisez ceci: 

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

Malheureusement pour API lvl <= 10, je n'ai pas encore trouvé de solution propre à cette . La solution "DontHackAndroidLikeThis" est en réalité un pur hackery. Tu ne devrais pas faire ça. :)

Edit: Selon le commentaire de @ Ben Pearson , pour l’API <= 10, on peut maintenant utiliser IntentCompat class pour les mêmes fonctions. On peut utiliser le drapeau IntentCompat.FLAG_ACTIVITY_CLEAR_TASK pour effacer la tâche. Vous pouvez donc également prendre en charge la pré-API niveau 11. 

579
Akos Cz

Cas 1: Seulement deux activités A et B:  

Ici, le flux d’activités est A-> B. Si vous cliquez sur le bouton Précédent de B, vous devez fermer l’application puis, tout en démarrant l’activité B à partir de A juste un appel terminé (), cela empêchera Android de stocker l’activité A dans le Backstack.eg pour l’activité A Écran d’application Loding/Splash.

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();

Cas 2: Plus de deux activités:  

S'il y a un flux comme A-> B-> C-> D-> B et en cliquant sur le bouton de retour de l'activité B en sortant de l'activité D. Dans ce cas, nous devrions utiliser.

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);

Ici l'activité B sera démarrée à partir du backstack plutôt que d'une nouvelle instance à cause d'Intent.FLAG_ACTIVITY_CLEAR_TOP et d'Intent.FLAG_ACTIVITY_NEW_TASK efface la pile et en fait le premier. Ainsi, lorsque nous appuierons sur le bouton de retour, l'application entière sera terminée.

43
monish george

Avec la nouvelle version d'Android> = API 16, utilisez finishAffinity()

l'approche convient pour> = API 16.

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
  • Cela revient à démarrer une nouvelle activité et à effacer toute la pile. 
  • OU Redémarrez sur MainActivity/FirstActivity.
28
karan

J'ai également passé quelques heures là-dessus ... et je suis d'accord pour dire que FLAG_ACTIVITY_CLEAR_TOP ressemble à ce que vous souhaitez: effacez la pile entière, à l'exception de l'activité en cours de lancement, de sorte que le bouton Précédent permet de quitter l'application. Cependant, comme l'a mentionné Mike Repass, FLAG_ACTIVITY_CLEAR_TOP ne fonctionne que lorsque l'activité que vous lancez est déjà dans la pile. quand l'activité n'est pas là, le drapeau ne fait rien.

Que faire? Placez l'activité en cours de lancement dans la pile avec FLAG_ACTIVITY_NEW_TASK, ce qui fait de cette activité le début d'une nouvelle tâche dans la pile d'historique. Ajoutez ensuite l'indicateur FLAG_ACTIVITY_CLEAR_TOP.

Désormais, lorsque FLAG_ACTIVITY_CLEAR_TOP ira chercher la nouvelle activité dans la pile, elle sera là et sera extraite avant que tout le reste ne soit effacé.

Voici ma fonction de déconnexion; le paramètre View est le bouton auquel la fonction est attachée.

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}
19
user2895402

Vous ne devriez pas changer la pile. Le bouton de retour Android devrait fonctionner comme dans un navigateur Web.

Je peux penser à un moyen de le faire, mais c'est un sacré bidouillage.

  • Faites vos activités singleTask en l'ajoutant à la AndroidManifest Exemple:

    <activity Android:name=".activities.A"
              Android:label="@string/A_title"
              Android:launchMode="singleTask"/>
    
    <activity Android:name=".activities.B"
              Android:label="@string/B_title"
              Android:launchMode="singleTask"/>
    
  • Étendez Application qui tiendra la logique de l'endroit où aller.

Exemple:

public class DontHackAndroidLikeThis extends Application {

  private Stack<Activity> classes = new Stack<Activity>();

  public Activity getBackActivity() {
    return classes.pop();
  }

  public void addBackActivity(Activity activity) {
    classes.Push(activity);
  }
}

De A à B:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class); 
startActivity(this, B.class);

De B ​​à C:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class); 
startActivity(this, C.class);

En C:

If ( shouldNotGoBackToB() ) {
  DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
  app.pop();
}

et manipuler le bouton de retour à pop() de la pile.

Encore une fois, vous ne devriez pas faire ça :)

12
Macarse

Immédiatement après avoir démarré une nouvelle activité, à l’aide de startActivity, veillez à appeler finish() afin que l’activité en cours ne se superpose pas à la nouvelle.

11
Keith Maurino

Essaye ça:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
4
Mohammad
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
1
Neeraj Gupta

Essayez ci-dessous le code,

Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK| 
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
0
shashikant yadav

Pour moi aucune des méthodes ci-dessus ne fonctionne pas.

Il suffit de faire ceci pour effacer toutes les activités précédentes :

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
0