Wie verwenden Sie Intent.FLAG_ACTIVITY_CLEAR_TOP, um den Aktivitätsstapel zu löschen?

84

Ich habe mehrere Beiträge darüber gelesen, muss aber etwas vermissen, da es bei mir nicht funktioniert. Meine Aktivität A hat im Manifest den Startmodus = "singleTop". Es startet Aktivität B mit launchmode = "singleInstance". Aktivität B öffnet einen Browser und empfängt und beabsichtigt zurück, weshalb es sich um singleInstance handelt. Ich versuche, die Zurück-Schaltfläche zu überschreiben, damit der Benutzer zur Aktivität A zurückgeschickt wird, und kann dann Zurück drücken, um die Aktivität zu verlassen, anstatt wieder zur Aktivität B zurückzukehren.

// activity B
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
 if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
  && keyCode == KeyEvent.KEYCODE_BACK
  && event.getRepeatCount() == 0) onBackPressed();
 return super.onKeyDown(keyCode, event);
}
@Override
public void onBackPressed() {
 startActivity(new Intent(this, UI.class)
 .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
 return;
}

Nach der Rückkehr vom Browser lautet der Stapel ... A, B, Browser, B.

Ich erwarte, dass dieser Code den Stapel in ... A ... ändert, sodass der Benutzer durch erneutes Drücken zurück zum Startbildschirm zurückkehrt.

Stattdessen scheint es den Stapel in ... A, B, Browser, B, A ... zu ändern, als ob diese Flags nicht da wären.

Ich habe versucht, finish () in Aktivität B nach startActivity aufzurufen, aber dann bringt mich die Zurück-Schaltfläche wieder zurück zum Browser!

Was vermisse ich? Vielen Dank!

piusvelte
quelle

Antworten:

72

@bitestar hat die richtige Lösung, aber es gibt noch einen Schritt:

Es wurde in den Dokumenten versteckt, aber Sie müssen das launchModevon Activityzu etwas anderem als ändern standard. Andernfalls wird es zerstört und neu erstellt, anstatt nach oben zurückgesetzt zu werden.

ScouseChris
quelle
51
Eigentlich ... Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPwird genau das tun.
Derk-Jan
Überprüfen Sie die Lösung von Steel_fedex auf ihr Beispiel.
Darpan
2
Wo zum Teufel ist die Lösung von Steel_fedex?!
ChangWon Jeong Juicycool
112

Ich habe Aktivität A-> B-> C-> D gestartet. Wenn die Zurück-Taste auf Aktivität DI gedrückt wird, möchten Sie zu Aktivität A gehen. Da A mein Ausgangspunkt ist und sich daher bereits auf dem Stapel befindet, werden alle Aktivitäten über A gelöscht und Sie können von A aus nicht zu einer anderen Aktivität zurückkehren .

Dies funktioniert tatsächlich in meinem Code:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        Intent a = new Intent(this,A.class);
        a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(a);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}       
Jesper Bischoff-Jensen
quelle
4
Diese Lösung schließt alle Zwischenaktivitäten. aber auch Neustart der RootActivity. Sie können die unten stehende Lösung von @ Steel_Fedex überprüfen. Es macht dasselbe, startet RootActivity jedoch nicht neu.
Darpan
Dies ist die beste Lösung für meinen Fall. Ich möchte eigentlich, dass die Root-Aktivität wieder startet
Tash Pemhiwa
24

Dafür benutze ich FLAG_ACTIVITY_CLEAR_TOPFlag zum Starten Intent
(ohne FLAG_ACTIVITY_NEW_TASK)

und launchMode = "singleTask"im Manifest für gestartete Aktivitäten.

Scheint so, als würde es so funktionieren, wie ich es brauche - die Aktivität wird nicht neu gestartet und alle anderen Aktivitäten werden geschlossen.

Fedir Tsapana
quelle
Ich habe überprüft, Lösung von Bitster funktioniert nicht. Während diese Lösung funktionierte. RootActivity wurde nicht neu gestartet.
Darpan
Wähle deine Worte klüger. Bitestar-Lösung funktioniert tatsächlich!
Jesper Bischoff-Jensen
singleTask funktioniert für mich, sodass die Aktivität nicht neu erstellt und das Ereignis in onNewIntent behandelt wird.
Jishi Chen
11

Obwohl diese Frage bereits genügend Antworten hat, dachte ich, jemand möchte wissen, warum diese Flagge auf diese besondere Weise funktioniert. Dies habe ich in der Android-Dokumentation gefunden

Die aktuell ausgeführte Instanz von Aktivität B im obigen Beispiel erhält entweder die neue Absicht, die Sie hier in ihrer onNewIntent () -Methode starten, oder wird selbst beendet und mit der neuen Absicht neu gestartet.

Wenn der Startmodus als "mehrfach" (Standardeinstellung) deklariert wurde und Sie FLAG_ACTIVITY_SINGLE_TOP nicht in derselben Absicht festgelegt haben, wird er beendet und neu erstellt. Für alle anderen Startmodi oder wenn FLAG_ACTIVITY_SINGLE_TOP festgelegt ist, wird diese Absicht an onNewIntent () der aktuellen Instanz übergeben.


Also entweder
1 . Ändern Sie die launchModeAktivität A in etwas anderes als Standard (dh singleTaskoder etwas). Dann FLAG_ACTIVITY_CLEAR_TOPstartet Ihre Flagge Ihre Aktivität A nicht neu.

oder,

2 . Verwenden Sie Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPals Ihre Flagge. Dann wird es so funktionieren, wie Sie es wünschen.

Darpan
quelle
8

Ich benutze drei Flags, um das Problem zu lösen:

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK | 
                Intent.FLAG_ACTIVITY_NEW_TASK);
Houssin Boulla
quelle
4

Android hinzufügen: noHistory = "true" in der Manifestdatei.

<manifest >
        <activity
            android:name="UI"
            android:noHistory="true"/>

</manifest>
Ahmad Aghazadeh
quelle
Zum ersten Mal sehen Sie diese Flagge, aber es hat für meinen Fall funktioniert, danke
vlasentiy
3

Ich rief an, activity_name.this.finish()nachdem ich neue Absichten gestartet hatte und es funktionierte für mich.

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

Aber es wird bei mir nicht funktionieren ... Ich schlage diese Lösung nicht zur Verwendung vor, aber wenn das Setzen des Flags bei Ihnen nicht funktioniert, können Sie dies versuchen. Trotzdem empfehle ich, sie nicht zu verwenden

Swap-IOS-Android
quelle
2

Ich weiß, dass es bereits eine akzeptierte Antwort gibt, aber ich sehe nicht, wie es für das OP funktioniert, weil ich FLAG_ACTIVITY_CLEAR_TOP in seinem speziellen Fall nicht für sinnvoll halte. Dieses Flag ist nur für Aktivitäten in derselben Aufgabe relevant . Basierend auf seiner Beschreibung hat jede Aktivität ihre eigene Aufgabe : A, B und den Browser.

Etwas, das ihn vielleicht abschreckt, ist, dass A singleTop ist, wenn es singleTask sein sollte. Wenn A singleTop ist und B A startet, wird ein neues A erstellt, da A nicht in der Aufgabe von B ist. Aus der Dokumentation zu singleTop:

"Wenn eine Instanz der Aktivität bereits oben in der aktuellen Aufgabe vorhanden ist , leitet das System die Absicht an diese Instanz weiter ..."

Da B A startet, ist die aktuelle Aufgabe die Aufgabe von B, die für eine einzelne Instanz bestimmt ist und daher A nicht enthalten kann. Verwenden Sie singleTask, um dort das gewünschte Ergebnis zu erzielen, da das System dann die Aufgabe mit A findet und diese Aufgabe in den Vordergrund rückt.

Nachdem B A gestartet hat und der Benutzer von A zurückgedrückt hat, möchte das OP weder B noch den Browser sehen. Um dies zu erreichen, ist der Aufruf von finish () in B korrekt. Auch hier entfernt FLAG_ACTIVITY_CLEAR_TOP die anderen Aktivitäten in A's Aufgabe nicht, da sich seine anderen Aktivitäten alle in unterschiedlichen Aufgaben befinden. Das Stück, das ihm fehlte, ist jedoch, dass B auch FLAG_ACTIVITY_NO_HISTORY verwenden sollte, wenn die Absicht für den Browser ausgelöst wird. Hinweis: Wenn der Browser bereits vor dem Starten der OP-Anwendung ausgeführt wird, wird der Browser natürlich beim Zurückdrücken von A angezeigt. Um dies wirklich zu testen, müssen Sie den Browser vor dem Starten der Anwendung verlassen.

Kevin
quelle
1

FLAG_ACTIVITY_NEW_TASK ist hier das Problem, das eine neue Aufgabe initiiert. Entfernen Sie sie einfach und Sie sind fertig.

Nun, ich empfehle Ihnen zu lesen, was jede Flagge tut, bevor Sie mit ihnen arbeiten

Lesen Sie diese & Intent Flags hier

100rabh
quelle
1
Ich habe die Flagge gelesen und es klang wie das, was ich brauchte. Unabhängig davon hat das Entfernen von FLAG_ACTIVITY_NEW_TASK keine Auswirkungen auf das Ergebnis. Es ist immer noch eine endlose Zurück-Knopf-Schleife ... A-> B, zurück zu A, zurück zu B, zurück zu A ...
piusvelte
Sind Sie sicher, warum Sie B als singleInstance verwenden? Eine "singleInstance" -Aktivität verhält sich so,
100rabh
B muss die vom Browser zurückgerufene Absicht erhalten. Ich habe versucht, den Startmodus in singleTask zu ändern, und das funktioniert immer noch, aber die Schleife der Zurück-Taste tritt immer noch auf.
Piusvelte
Ich denke, es hat nicht funktioniert, weil Sie dort FLAG_ACTIVITY_NEW_TASK verwendet haben. Verwenden Sie besser nur FLAG_ACTIVITY_CLEAR_TOP und vermeiden Sie die Verwendung von singleTask oder singleInstance
100rabh
1
Ich denke, das sollte eine funktionierende Lösung sein, wenn Sie hinzufügen Intent.FLAG_ACTIVITY_SINGLE_TOP, um die Neuerstellung zu verhindern
yonojoy
1

Anfangs hatte ich auch Probleme, FLAG_ACTIVITY_CLEAR_TOP zum Laufen zu bringen. Schließlich habe ich es zum Laufen gebracht, indem ich den Wert davon (0x04000000) verwendet habe. Es sieht also so aus, als gäbe es ein Eclipse / Compiler-Problem. Aber leider wird die überlebende Aktivität neu gestartet, was ich nicht will. Es sieht also so aus, als gäbe es keine einfache Lösung.

ja_chu
quelle