Jak używasz Intent.FLAG_ACTIVITY_CLEAR_TOP do czyszczenia stosu aktywności?

85

Przeczytałem kilka postów na temat korzystania z tego, ale chyba czegoś brakuje, ponieważ nie działa dla mnie. Moje działanie A ma launchmode = "singleTop" w manifeście. Rozpoczyna czynność B z launchmode = "singleInstance". Działanie B otwiera przeglądarkę i odbiera i zwraca z powrotem, dlatego jest to singleInstance. Próbuję zastąpić przycisk Wstecz, aby użytkownik został odesłany z powrotem do działania A, a następnie mógł nacisnąć przycisk Wstecz, aby opuścić działanie, zamiast wracać do działania B.

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

Po powrocie z przeglądarki stos to ... A, B, Browser, B

Oczekuję, że ten kod zmieni stos na ... A ... tak, że ponowne naciśnięcie przeniesie użytkownika z powrotem do ekranu głównego.

Zamiast tego wydaje się, że zmienia stos na ... A, B, Browser, B, A ... tak, jakby tych flag nie było.

Próbowałem wywołać finish () w działaniu B po startActivity, ale potem przycisk Wstecz przenosi mnie z powrotem do przeglądarki!

czego mi brakuje? Dziękuję Ci!

piusvelte
źródło

Odpowiedzi:

72

@bitestar ma poprawne rozwiązanie, ale jest jeszcze jeden krok:

Został on ukryty w docs, jednak trzeba zmienić launchModez Activityinną niż standard. W przeciwnym razie zostanie zniszczony i odtworzony zamiast resetowania do góry.

ScouseChris
źródło
52
Właściwie ... Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPwystarczy.
Derk-Jan,
Sprawdź przykład rozwiązania Steel_fedex.
Darpan,
2
więc gdzie do diabła jest rozwiązanie Steel_fedex ?!
ChangWon Jeong Juicycool
112

Rozpocząłem Ćwiczenie A-> B-> C-> D. Kiedy przycisk Wstecz zostanie naciśnięty w działaniu D, chcę przejść do działania A. Ponieważ A jest moim punktem początkowym, a zatem już na stosie, wszystkie działania na górze A są wyczyszczone i nie można wrócić do żadnego innego działania z A .

To faktycznie działa w moim kodzie:

@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
źródło
4
To rozwiązanie zamyka wszystkie działania pośredniczące; ale także ponowne uruchomienie RootActivity. Możesz sprawdzić rozwiązanie @ Steel_Fedex poniżej. Robi to samo, ale nie uruchamia ponownie RootActivity.
Darpan,
To najlepsze rozwiązanie w moim przypadku. Właściwie chcę, aby aktywność roota ponownie się uruchomiła
Tash Pemhiwa,
24

W tym celu używam FLAG_ACTIVITY_CLEAR_TOPflagi do uruchamiania Intent
(bez FLAG_ACTIVITY_NEW_TASK)

i jako launchMode = "singleTask"manifest do rozpoczętej działalności.

Wygląda na to, że działa tak, jak potrzebuję - aktywność nie uruchamia się ponownie, a wszystkie inne są zamknięte.

Fedir Tsapana
źródło
Sprawdziłem, rozwiązanie Bitster nie działa. Chociaż to rozwiązanie zadziałało. RootActivity nie uruchomiło się ponownie.
Darpan
Mądrzej dobieraj słowa. Rozwiązanie Bitestar faktycznie działa!
Jesper Bischoff-Jensen
singleTask działa dla mnie, więc Activity nie będzie odtwarzać i obsługiwać zdarzenia w onNewIntent.
Jishi Chen
11

Chociaż to pytanie ma już wystarczające odpowiedzi, pomyślałem, że ktoś chciałby wiedzieć, dlaczego ta flaga działa w tak dziwny sposób, oto, co znalazłem w dokumentacji Androida

Aktualnie działające wystąpienie działania B w powyższym przykładzie otrzyma nową intencję, którą zaczynasz tutaj, w swojej metodzie onNewIntent () lub zostanie zakończone i uruchomione ponownie z nową intencją.

Jeśli zadeklarował tryb uruchamiania jako „wiele” (domyślny) i nie ustawiłeś FLAG_ACTIVITY_SINGLE_TOP w tym samym celu, zostanie zakończony i ponownie utworzony; dla wszystkich innych trybów uruchamiania lub jeśli ustawiono FLAG_ACTIVITY_SINGLE_TOP, to intencja zostanie dostarczona do onNewIntent () bieżącej instancji.


Tak więc,
1 . ZmienićlaunchMode działanie A na coś innego ze standardowego (np. singleTaskLub coś). Wtedy twoja flaga FLAG_ACTIVITY_CLEAR_TOPnie uruchomi ponownie Twojej Aktywności A.

lub,

2 . Użyj Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPjako swojej flagi. Wtedy będzie działać tak, jak chcesz.

Darpan
źródło
8

Używam trzech flag, aby rozwiązać problem:

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK | 
                Intent.FLAG_ACTIVITY_NEW_TASK);
Houssin Boulla
źródło
4

Dodaj android: noHistory = "true" w pliku manifestu.

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

</manifest>
Ahmad Aghazadeh
źródło
Pierwszy raz widzę tę flagę, ale zadziałała w moim przypadku, dzięki
vlasentiy
3

zadzwoniłem activity_name.this.finish()po rozpoczęciu nowej intencji i to zadziałało.

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

Ale to nie zadziała ... Nie proponuję tego rozwiązania do użycia, ale jeśli ustawienie flagi nie zadziała, możesz spróbować ... Ale nadal nie polecam go używać

Swap-IOS-Android
źródło
2

Wiem, że istnieje już zaakceptowana odpowiedź, ale nie widzę, jak to działa w przypadku OP, ponieważ nie sądzę, aby FLAG_ACTIVITY_CLEAR_TOP miała sens w jego konkretnym przypadku. Ta flaga ma znaczenie tylko w przypadku działań w tym samym zadaniu . Opierając się na jego opisie, każda czynność ma swoje własne zadanie : A, B i przeglądarka.

Coś, co może go wytrącać, to fakt, że A to singleTop, podczas gdy powinno być singleTask. Jeśli A jest singleTop, a B zaczyna A, to zostanie utworzone nowe A, ponieważ A nie znajduje się w zadaniu B. Z dokumentacji dla singleTop:

„Jeśli instancja działania już istnieje na początku bieżącego zadania , system kieruje intencję do tej instancji…”

Ponieważ B rozpoczyna A, bieżące zadanie jest zadaniem B, które jest przeznaczone dla pojedynczej Instancji i dlatego nie może zawierać A. Użyj funkcji singleTask, aby osiągnąć tam pożądany rezultat, ponieważ wtedy system znajdzie zadanie, które ma A i przeniesie to zadanie na pierwszy plan.

Wreszcie, po tym, jak B uruchomił A, a użytkownik naciśnie z powrotem z A, OP nie chce widzieć ani B, ani przeglądarki. Aby to osiągnąć, wywołanie finish () w B jest poprawne; ponownie FLAG_ACTIVITY_CLEAR_TOP nie usunie innych działań z zadania A, ponieważ wszystkie jego pozostałe działania należą do innych zadań. Brakowało mu jednak tego, że B powinien również używać FLAG_ACTIVITY_NO_HISTORY podczas odpalania intencji w przeglądarce. Uwaga: jeśli przeglądarka jest już uruchomiona jeszcze przed uruchomieniem aplikacji OP, to oczywiście zobaczysz przeglądarkę po naciśnięciu wstecz z A. Aby naprawdę to przetestować, wyjdź z przeglądarki przed uruchomieniem aplikacji.

Kevin
źródło
1

FLAG_ACTIVITY_NEW_TASK jest tutaj problemem, który inicjuje nowe zadanie. Po prostu je usuń i gotowe.

Cóż, polecam przeczytać, co robi każda flaga przed rozpoczęciem pracy z nimi

Przeczytaj to & Flagi intencji tutaj

100rabh
źródło
1
Przeczytałem flagę i brzmiało jak to, czego potrzebowałem. Niezależnie od tego, usunięcie FLAG_ACTIVITY_NEW_TASK nie ma wpływu na wynik. To wciąż niekończąca się pętla przycisku wstecz ... A-> B, z powrotem do A, z powrotem do B, z powrotem do A ...
piusvelte
Czy jesteś pewien, dlaczego używasz B jako singleInstance? Aktywność AA „singleInstance” działa tak, jakby FLAG_ACTIVITY_NEW_TASK była w intencji. Sprawdź developer.android.com/guide/topics/fundamentals.html
100rabg
B musi otrzymać intencję oddzwonioną z przeglądarki. Próbowałem zmienić tryb uruchamiania na singleTask i to nadal działa, ale nadal występuje pętla przycisku Wstecz.
piusvelte
Myślę, że to nie zadziałało, ponieważ użyłeś tam FLAG_ACTIVITY_NEW_TASK Lepiej używaj tylko FLAG_ACTIVITY_CLEAR_TOP i unikaj używania ani singleTask, ani singleInstance
100rabh
1
Myślę, że powinno to być działające rozwiązanie, jeśli dodasz, Intent.FLAG_ACTIVITY_SINGLE_TOPaby zapobiec odtworzeniu
yonojoy
1

Na początku miałem też problem z uruchomieniem FLAG_ACTIVITY_CLEAR_TOP. W końcu udało mi się go uruchomić, używając jego wartości (0x04000000). Wygląda na to, że wystąpił problem z Eclipse / kompilatorem. Ale niestety aktywność, która przetrwała, zostaje wznowiona, co nie jest tym, czego chcę. Wygląda na to, że nie ma łatwego rozwiązania.

ja_chu
źródło