Android: Wyczyść stos aktywności

134

W mojej aplikacji mam kilka działań. a przepływ jest bardzo skomplikowany. Po kliknięciu aplikacji Logout następuje przejście do ekranu logowania i stamtąd użytkownik może wyjść za pomocą przycisku anulowania (dzwonienie system.exit(0))

kiedy wychodzę lub cofam, system wywołuje działanie ze stosu :( jak mogę wyczyścić wszystkie działania na stosie po przejściu do ekranu logowania? wywołanie finish()jest niepraktyczne, ponieważ jest tak wiele działań, a niektóre działania nie powinny być zamykane, gdy są one aktywne, na przykład wywołujące aktywność aparatu natywnego.

validateuser logoutuser = new validateuser();
logoutuser.logOut();
Intent loginscreen = new Intent(homepage.this, Login2.class);
(homepage.this).finish();
loginscreen.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(loginscreen);
Jay Mayu
źródło
Możliwy duplikat Androida: Wyczyść tylny stos
Mehdi Dehghani

Odpowiedzi:

345

Większość z was się myli. Jeśli chcesz zamknąć istniejący stos aktywności niezależnie od tego, co tam jest i utworzyć nowy root, prawidłowy zestaw flag jest następujący:

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

Z dokumentu :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Dodano na poziomie API 11

Jeśli zostanie ustawiona w intencji przekazanej do Context.startActivity(), ta flaga spowoduje, że wszelkie istniejące zadanie, które byłoby skojarzone z działaniem, zostanie wyczyszczone przed rozpoczęciem działania. Oznacza to, że czynność staje się nowym źródłem pustego zadania, a wszelkie stare czynności są zakończone. Tego można używać tylko w połączeniu z FLAG_ACTIVITY_NEW_TASK.

Cynichniy Bandera
źródło
Działał doskonale. Dzięki. O dziwo nie dał błędu z minSDK = 9.
Mahm00d,
Szczerze mówiąc, nigdy nie korzystałem z tej funkcji, wskrzeszałem po awarii itp., A raczej skupiłem się na naprawieniu problemów, które spowodowały awarię)
Cynichniy Bandera
Ta sama funkcjonalność zapewnia również IntentCompat.makeRestartActivityTaskbiblioteka wsparcia.
sealskej
Dodanie tylko tych dwóch flag pozostawia ścieżkę stosu aktywności za sobą (zaczyna się od poprzedniej), a następnie dodaje Intent.FLAG_ACTIVITY_CLEAR_TOP, co po prostu ponownie uruchamia aplikację, a następnie całkowicie ją kończy. Nie dodałem żadnej flagi do działań jawnie. Jaki może być problem?
Farid
1
Jeden z najlepszych początków: „Większość z was się myli”.
Nibbana
31

Kiedy dzwonisz startActivityna ostatnią czynność, z której zawsze możesz skorzystać

Intent.FLAG_ACTIVITY_CLEAR_TOP

jako flaga w tym zamiarze.

Przeczytaj więcej o fladze tutaj .

David Olsson
źródło
to też nie pomaga. Po prostu wyświetlam działanie, które nie kończy się na finish (); :(
Jay Mayu
Myślę, że FLAG_ACTIVITY_CLEAR_TOP czyści działania na górze. Mój problem to działania na dole :(
Jay Mayu,
Myślę, że to zależy od tego, jak faktycznie przebiega przepływ. Więcej na ten temat można przeczytać tutaj: developer.android.com/reference/android/content/ ... and developer.android.com/guide/topics/fundamentals/ ...
David Olsson,
7
Dzięki za pokazanie odpowiednich zasobów. popełniłem błąd polegający na zamknięciu aktywności logowania. Nie powinnam go zamykać. Kiedy czynność została załadowana jako pierwsza. więc kiedy oddzwaniam do niego za pomocą flagi Clear_top, aktywność logowania usuwa wszystkie działania na górze. ponieważ logowanie jest pierwszym działaniem wstępnym, usuwa wszystkie działania rozpoczęte później. więc bingo to zadziałało :)
Jay Mayu
13
Z dokumentacji, FLAG_ACTIVITY_CLEAR_TOP czyści stos tylko wtedy, gdy określona czynność „jest już uruchomiona w bieżącym zadaniu”
AlikElzin-kilaka
16

Oto prosta metoda pomocnicza do rozpoczynania nowej aktywności jako nowej najwyższej aktywności, która działa od poziomu API 4 do obecnej wersji 17:

static void startNewMainActivity(Activity currentActivity, Class<? extends Activity> newTopActivityClass) {
    Intent intent = new Intent(currentActivity, newTopActivityClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
    currentActivity.startActivity(intent);
}

nazwij to w ten sposób od swojej bieżącej aktywności:

startNewMainActivity(this, MainActivity.class);
whlk
źródło
1
Czy nie mógłbyś niż zwykle użyć intent.addFlags (0x8000); i uprościć to?
Davor,
Ponieważ ta flaga została po raz pierwszy wprowadzona w Honeycomb, nie mam pojęcia, jakie konsekwencje może mieć we wcześniejszych wersjach. Więc to ja byłem precaucios. Ale wydaje mi się, że usunięcie konspektu nie powinno stanowić problemu.
ok.
1
Aby dodać tę flagę, gdy poziom API jest <11 to trzeba zrobić Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBjeszcze intent.addFlags(0x8000);nigdy nie dodaje
Straw Hat
Każdemu użytkownikowi przechodzi wiele czynności jedna po drugiej przez intencje. Czy muszę coś robić, aby aplikacja nie uległa awarii przy zbyt dużej liczbie działań na stosie? Dzięki!
Ruchir Baronia
10

Wyczyść stan konta za pomocą poniższego kodu:

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

Gotowe

Hiren Patel
źródło
Każdemu użytkownikowi przechodzi wiele czynności jedna po drugiej przez intencje. Czy muszę coś robić, aby aplikacja nie uległa awarii przy zbyt dużej liczbie działań na stosie? Dzięki!
Ruchir Baronia
@RuchirBaronia, jeśli przejdziesz A -> B -> C -> D -> E -> F -> G -> H, teraz H -> ja piszę mój kod, to będę ostatnią aktywnością po tym naciśnięciu przycisku Wstecz aplikacja zostanie zamknięta, ponieważ aplikacja nie jest aktywna poza stanem, mam nadzieję, że to Ci pomoże.
Hiren Patel
Czy jednak muszę to zrobić? Co się stanie, jeśli nigdy nie wyczyszczę stosu aktywności?
Ruchir Baronia
@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
Hiren Patel
Ale od czasu do czasu pokazuje biały ekran podczas wywoływania nowej aktywności. Jak to rozwiązać?
Sagar
3

W moim przypadku LoginActivity również został zamknięty. W rezultacie,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

nie pomogło.

Jednak ustawienie

Intent.FLAG_ACTIVITY_NEW_TASK

pomogło mi.

Prashant Gami
źródło
Każdemu użytkownikowi przechodzi wiele czynności jedna po drugiej przez intencje. Czy muszę coś robić, aby aplikacja nie uległa awarii przy zbyt dużej liczbie działań na stosie? Dzięki!
Ruchir Baronia,
3
Intent intent = new Intent(LoginActivity.this, Home.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  //It is use to finish current activity
startActivity(intent);
this.finish();
Sakib Syed
źródło
1
dlaczego używasz zarówno this.finish()isetFlags() także do wyczyszczenia bieżącej aktywności?
Sagar
3

Zauważyłem, że prosiłeś o rozwiązanie, na którym nie można polegać finish(), ale zastanawiam się, czy to mimo wszystko pomoże.

Śledziłem, czy flaga wyjścia jest podnoszona za pomocą statycznej zmiennej klasy, która przetrwa cały okres życia aplikacji. W każdym odpowiednim działaniu onResume()użyj

@Override
public void onResume() {
    super.onResume();
    if (ExitHelper.isExitFlagRaised) {
        this.finish();
    }
}

Klasa ExitHelper

public class ExitHelper {
    public static boolean isExitFlagRaised = false;
}

Powiedzmy, że w mainActivity użytkownik naciska przycisk, aby wyjść - możesz ustawić ExitHelper.isExitFlagRaised = true; a następnie finish(). Następnie inne istotne działania, które zostaną automatycznie wznowione, również zostaną zakończone.

Kevin Lee
źródło
co się stanie, jeśli użyję kodu w MainActivity onresume (), a następnie wrócę do mainactivity z drugiego działania onbackpress
Mithu
3

Ta decyzja działa dobrze:

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

Ale nowa aktywność zaczyna się długo i jakiś czas pojawia się biały ekran. Jeśli jest to krytyczne, zastosuj to obejście:

public class BaseActivity extends AppCompatActivity {

    private static final String ACTION_FINISH = "action_finish";

    private BroadcastReceiver finisBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        registerReceiver(finisBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                finish();
            }
        }, new IntentFilter(ACTION_FINISH));
    }

    public void clearBackStack() {
        sendBroadcast(new Intent(ACTION_FINISH));
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(finisBroadcastReceiver);
        super.onDestroy();
    }
}

Jak to wykorzystać:

public class ActivityA extends BaseActivity {

    // Click any button
    public void startActivityB() {
        startActivity(new Intent(this, ActivityB.class));
        clearBackStack();
    }
}

Wada: wszystkie działania, które muszą zostać zamknięte na stosie, muszą być rozszerzeniem BaseActivity

maXp
źródło
3

W przypadku deweloperów platformy Xamarin możesz użyć:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
BYISHIMO Audace
źródło
1

Korzystanie z Kotlin:

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

intent.flags = FLAG_ACTIVITY_NEW_TASK or 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()
Gibolt
źródło
0

Zamiar zamiaru = nowy zamiar (LoginActivity.this, MainActivity.class); intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity (intencja); koniec();

Raviraj
źródło