Android: Usuń wszystkie poprzednie czynności z tylnego stosu


119

Kiedy klikam przycisk Wyloguj w mojej aktywności profilu, chcę przenieść użytkownika na stronę logowania , gdzie musi użyć nowych poświadczeń.

Dlatego użyłem tego kodu:

Intent intent = new Intent(ProfileActivity.this,
        LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

w onButtonClickprzycisku Wyloguj.

Ale problem polega na tym, że kiedy klikam przycisk wstecz na urządzeniu w aktywności logowania, przenosi mnie do ProfileActivity. Spodziewałem się, że aplikacja powinna zostać zamknięta po naciśnięciu przycisku Wstecz urządzenia w LoginActivity.

Co ja robię źle?

Dodałem również android:launchMode="singleTop"w manifeście dla mojego LoginActivity

Dziękuję Ci


@GauravVashisth Właśnie podążałem za tym rozwiązaniem stackoverflow.com/questions/5794506/ ...
Archie.bpgc

@ abbas.aniefa To rozwiązanie jest nieco skomplikowane. Czy to jedyny sposób, aby wyczyścić cały tylny stos. Ponieważ mam
ponad

spróbuj tego więc, stackoverflow.com/questions/10961481/… . Korzystanie z transmisji jest lepszym rozwiązaniem.
abbas.aniefa

inne podejście, którego możesz użyć do wylogowania, po wylogowaniu zapisz jedną flagę we wspólnych preferencjach iw każdej metodzie onRestart () działania możesz sprawdzić wartość tej zmiennej, jeśli jest ustawiona na true, możesz zakończyć bieżące działanie. więc bez względu na to, ile działań jest otwartych w tle. to zakończyłoby całą twoją działalność.
Hiren Dabhi

Twój oryginalny kod faktycznie działa na poziomie API 11 lub wyższym z poprawką. Wystarczy, że intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
złożysz

Odpowiedzi:


303

Zaproponowane tutaj rozwiązanie zadziałało u mnie:

Jawa

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Kotlin

val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)

Jednak wymaga poziomu API> = 11.


Chłopaki, przeczytaj dokumentację FLAG_ACTIVITY_CLEAR_TASK.To jest oficjalny sposób na zdobycie. Nie musisz zmieniać wszystkich działań w aplikacji.
AlikElzin-kilaka

To nie działa w przypadku powiadomień stackoverflow.com/questions/24873131/ ...
Sam

Mam moje minAPI = 16, więc dla mnie działa idealnie. Jednak zauważyłem, że wykonanie widoku jest nieco powolne z API> 21 i płynne z interfejsami API <21. Czy ktoś ma ten sam problem?
Red M

1
Spowoduje to utworzenie nowego zadania do działań
Rohit

@kgiannakakis Bez wątpienia rozwiązanie działa, jeśli mamy tylko jedno zadanie (stos aktywności), ale gdy mamy wiele zadań (stos aktywności), nie działa. np. powiedzmy, że mam cztery działania dla mojej aplikacji A, B, C i D. Załóżmy, że mam dwa stosy pleców Aktywności A-> B-> C (tło) i D-> A-> B (pierwszy plan) i Jeśli ja wywołaj aktywność A z mojego obecnego stosu (D-> A-> B) z filtrem intencji to, co zasugerowałeś, co się stanie, wyczyści mój obecny stos (D-> A-> B) i otwórz działanie A, a kiedy wrócę, zamknij aplikacja, ale jeśli naciśnę przycisk ostatniej aplikacji, widzę tam dwa stosy mojej aplikacji.
Rahul Pareta

31

Oto jedno rozwiązanie, aby wyczyścić wszystkie działania aplikacji po użyciu przycisku wylogowania.

Za każdym razem, gdy zaczynasz działanie, zacznij je w ten sposób:

Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);

Jeśli chcesz zamknąć całą aplikację, zrób to:

setResult(RESULT_CLOSE_ALL);
finish();

RESULT_CLOSE_ALL to końcowa zmienna globalna z unikalną liczbą całkowitą sygnalizującą, że chcesz zamknąć wszystkie działania.

Następnie zdefiniuj onActivityResult(...)wywołanie zwrotne każdego działania, więc gdy działanie zwraca z wartością RESULT_CLOSE_ALL, wywołuje również finish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode)
    {
    case RESULT_CLOSE_ALL:
        setResult(RESULT_CLOSE_ALL);
        finish();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Spowoduje to efekt kaskady, który zamknie wszystkie twoje działania.

Jest to jednak hack i wykorzystuje startActivityForResultw sposób, który nie został zaprojektowany do użytku.

Być może lepszym sposobem na to byłoby użycie odbiorników telewizyjnych, jak pokazano tutaj:

Po wylogowaniu wyczyść stos historii aktywności, zapobiegając otwieraniu Aktywności tylko po zalogowaniu się za pomocą przycisku „Wstecz”

Zobacz te wątki również dla innych metod:

Android: Wyczyść tylny stos

Zakończ wszystkie poprzednie czynności


4
Czy jest to wykonalne, gdy masz około 30 zajęć z historii?
Rakesh Gondaliya

4
Powinien być. Ale jeśli masz w historii 30 działań, możesz rozważyć zmianę projektu. 30 wydaje się trochę za dużo, a Android może sam ich zabić.
Anup Cowkur

1
Wydaje się, że to kiepski sposób. Odpowiedź @RakeshGondaliya wydaje się być uzasadniona. 30 może tylko liczba reprezentująca „dużą” liczbę działań. Ta odpowiedź wygląda lepiej: stackoverflow.com/a/3008684/243709
Aman Alam

Ta odpowiedź jest świetna. Możesz także użyć biblioteki EventBus do wysyłania wydarzeń do swoich działań w backstacku. github.com/greenrobot/EventBus
Stan

Lepiej używać prostej flagi „Intent.FLAG_ACTIVITY_CLEAR_TOP” z intencją
Naveen Rao

18

Aby całkowicie wyczyścić stos działań, chcesz utworzyć nowy stos zadań za pomocą TaskStackBuilder, na przykład:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

Spowoduje to nie tylko utworzenie nowego, czystego stosu zadań, ale także pozwoli na poprawne działanie przycisku „w górę”, jeśli Twoje LoginActivity ma aktywność nadrzędną.


1
To najlepszy sposób na zrobienie tego.
Paul Burke,

FLAG_ACTIVITY_NEW_TASKlub finishAffinity()nie działa dla mnie. Tylko ta odpowiedź rozwiązała cel.
TM

Jeśli opuszczę aplikację za pomocą przycisku Wstecz i wrócę za pomocą ikony aplikacji, zostanie ona otwarta w działaniu, które nazwałem tą metodą. Więc nie działa dla mnie.
Tgo1014

17

finishAffinity()dodane w API 16. Używaj ActivityCompat.finishAffinity()w poprzednich wersjach. Kiedy uruchomisz dowolną aktywność za pomocą intencji i zakończysz bieżącą aktywność. Teraz użyj ActivityCompat.finishAffinity()zamiast tego finish(). zakończy wszystkie skumulowane działania poniżej bieżącej aktywności. U mnie działa dobrze.


3
To właściwieActivityCompat.finishAffinity()
The Berga

finishAffinity()również kończy bieżącą czynność wszystkimi działaniami obecnymi na tylnym stosie o tym samym powinowactwie.
Neeraj Sewani

10

Co mi pomogło

Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);

5

Jedynym możliwym rozwiązaniem, które mogę zasugerować, jest dodanie android:launchMode="singleTop"w manifeście mojego ProfileActivity . a po kliknięciu wylogowania można się wylogować, uruchamiając ponownie LoginActivity. przy wylogowaniu możesz to nazwać.

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();

Zrobiłem to, co się stało: kiedy klikam przycisk Wstecz, przenosi mnie do Activty, skąd przyszedłem do ProfileActivity
Archie.bpgc

Może się tak zdarzyć, ponieważ doszedłeś do ProfileActivity poprzez wywołanie nowej intencji, a nie wywołanie finish (); Jak przychodzisz do ProfileActivity z innych zajęć poza LoginActivty?
Android

Przechodzę przez to samo pytanie. Myślę, że to nie zadziała, gdy intencja logowania została zniszczona przez system, powiedzmy z powodu braku pamięci.
user1914692

5

W przypadku API 11+ możesz użyć w Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASKnastępujący sposób:

Intent intent = new Intent(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);

Całkowicie usunie wszystkie poprzednie działania i rozpocznie nową.


4

Możesz spróbować finishAffinity(), zamyka wszystkie bieżące działania i działa na Androidzie 4.1 i nowszych


1
finishAffinity () dodana w API 16. Użyj ActivityCompat.finishAffinity () w poprzedniej wersji. U mnie działa dobrze.
Anurag Srivastava

2

Ja też mam ten sam problem.

w aktywności logowania to, co robię, to.

    Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
    finish();
    MainActivity.this.startActivity(myIntent);  

przy wylogowaniu

   Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
   finish();
   ActivityLoggedIn.this.startActivity(myIntent);

Działa to dobrze, ale kiedy jestem w ActivityLoggedIn i minimalizuję aplikację i klikam ikonę przycisku uruchamiania na szufladzie aplikacji, MainActivity zaczyna się od nowa: - / Używam flagi

android:LaunchMode:singleTask 

dla MainActivity.


2

Użyj następujących dla activity

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);

usuń flagę CLEAR_TASK do użycia fragmentów.

Mam nadzieję, że to może być przydatne dla niektórych osób.


1

Po prostu zachować

Intent intent = new Intent(ProfileActivity.this,
    LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);

4
To nie działa. Nadal mogę przejść do ProfileActivity za pomocą przycisku Wstecz
Archie.bpgc

1

Żadna z flag intencji nie działała dla mnie, ale tak to naprawiłem:

Kiedy użytkownik wylogowuje się z jednego działania, musiałem nadać komunikat z tego działania, a następnie odebrać go w działaniach, które chciałem zamknąć, po czym wywołuję finish (); i działa całkiem nieźle.


1

Spróbuj tego, to zadział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();

1

Na poziomie API 11 lub wyższym użyj FLAG_ACTIVITY_CLEAR_TASKi FLAG_ACTIVITY_NEW_TASKoflaguj na Intencie, aby wyczyścić cały stos aktywności.

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |  Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

0

Użyj tego

Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();

czy znasz setFlags i addFlags?
GvSharma


0

Zaawansowany Kotlin wielokrotnego użytku:

Możesz ustawić flagę bezpośrednio za pomocą metody ustawiającej. W Kotlinie orjest zamiennik dla bitowego Java lub |.

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

Jeśli planujesz używać tego regularnie, utwórz funkcję rozszerzenia zamiaru

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

Następnie możesz bezpośrednio wywołać tę funkcję przed rozpoczęciem intencji

intent.clearStack()

Jeśli potrzebujesz opcji dodawania dodatkowych flag w innych sytuacjach, dodaj opcjonalny parametr do funkcji rozszerzenia.

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.