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.
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.
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.
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);
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();
}
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 :)
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.
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();
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
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);
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)