Android: Limpar pilha de atividades

132

Estou tendo várias atividades no meu aplicativo. e o fluxo é muito complicado. Quando clico no aplicativo Logout, navega para a tela de login e a partir daí o usuário pode sair pelo botão Cancelar (chamando system.exit(0))

Quando eu saio ou o botão Voltar, o sistema chama uma atividade da pilha :( como posso limpar todas as atividades da pilha quando chego à tela de Login? A chamada finish()não é prática, pois há muitas atividades e algumas atividades não devem ser fechadas quando eles estão ativos, como atividade de chamada de câmera nativa.

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
fonte
Possível duplicata do Android: Limpe a pilha traseira
Mehdi Dehghani

Respostas:

339

A maioria de vocês está errada. Se você deseja fechar a pilha de atividades existente, independentemente do que está lá e criar uma nova raiz, o conjunto correto de sinalizadores é o seguinte:

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

Do documento :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Adicionado no nível 11 da API

Se definido em um Intent passado para Context.startActivity(), esse sinalizador fará com que qualquer tarefa existente que esteja associada à atividade seja limpa antes que a atividade seja iniciada. Ou seja, a atividade se torna a nova raiz de uma tarefa vazia e quaisquer atividades antigas são concluídas. Isso só pode ser usado em conjunto com FLAG_ACTIVITY_NEW_TASK.

Cynichniy Bandera
fonte
Funcionou perfeitamente. Obrigado. Estranhamente não deu erro com minSDK = 9.
Mahm00d
Sinceramente eu nunca usei essa funcionalidade, ressuscitar após acidente, etc., e bastante focado em corrigir os problemas que acidente causado)
Cynichniy Bandera
A mesma funcionalidade também fornece IntentCompat.makeRestartActivityTaskna biblioteca de suporte.
sealskej
Adicionar apenas esses dois sinalizadores deixa a trilha da pilha de atividades para trás (começa em cima do anterior) e, em seguida, adicionamos Intent.FLAG_ACTIVITY_CLEAR_TOP, que simplesmente reinicia o aplicativo e sai totalmente. Não adicionei nenhum sinalizador às atividades explicitamente. Qual poderia ser o problema?
Farid
1
Um dos melhores inícios: "A maioria de vocês está errada".
Nibbana
31

Quando você liga startActivitypara a última atividade, você sempre pode usar

Intent.FLAG_ACTIVITY_CLEAR_TOP

como uma bandeira nessa intenção.

Leia mais sobre a bandeira aqui .

David Olsson
fonte
isso também não ajuda. Eu apenas trago uma atividade que não terminou com finish (); :(
Jay Mayu
Acho que FLAG_ACTIVITY_CLEAR_TOP limpa as atividades na parte superior. Meu problema são as atividades na parte inferior :(
Jay Mayu 16/08
Eu acho que depende de como o fluxo realmente é. Você deve ler mais sobre ele aqui: developer.android.com/reference/android/content/... e developer.android.com/guide/topics/fundamentals/...
David Olsson
7
Obrigado por mostrar os recursos corretos. o erro que cometi foi encerrar a atividade de login. Eu não deveria fechá-lo. Quando a atividade foi carregada primeiro. portanto, quando ligo de volta usando o sinalizador Clear_top, a atividade de login limpa todas as atividades na parte superior. como o login é a primeira atividade de entrada, ele limpa todas as atividades iniciadas depois. assim bingo funcionou :)
Jay Mayu
13
A partir da documentação, FLAG_ACTIVITY_CLEAR_TOP limpa a pilha somente se a atividade específica "já em execução na tarefa atual"
AlikElzin-Kilaka
16

Aqui está um método auxiliar simples para iniciar uma nova atividade como a nova atividade principal que funciona desde o nível 4 da API até a versão atual 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);
}

chame assim da sua atividade atual:

startNewMainActivity(this, MainActivity.class);
whlk
fonte
1
Você não poderia usar apenas intent.addFlags (0x8000); e simplificar isso?
Davor
Como esse sinalizador foi introduzido pela primeira vez no Honeycomb, não tenho idéia de que implicação isso pode ter nas versões anteriores. Então, isso era eu sendo cauteloso. Mas acho que a remoção do condicional não deve ser um problema.
whlk 6/07/2013
1
você quer adicionar essa bandeira quando o nível API é <11, então você precisa fazer Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBoutra coisa intent.addFlags(0x8000);nunca vai acrescentou
chapéu de palha
Estou fazendo o usuário executar muitas atividades, uma após a outra, através de intenções. Preciso fazer alguma coisa para garantir que o aplicativo não trava com muitas atividades na pilha? Obrigado!
Ruchir Baronia
9

Apague a Atividade Backstate pelo código abaixo:

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);

Feito

Hiren Patel
fonte
Estou fazendo o usuário executar muitas atividades, uma após a outra, através de intenções. Preciso fazer alguma coisa para garantir que o aplicativo não trava com muitas atividades na pilha? Obrigado!
Ruchir Baronia
@RuchirBaronia, Se você vai A -> B -> C -> D -> E -> F -> G -> H, agora H -> I, você escreve meu código do que será a última atividade depois e depois pressiona o botão Voltar O aplicativo será fechado porque o aplicativo não possui atividade de backstate. Espero que isso ajude você.
precisa
Eu preciso fazer isso? O que acontecerá se eu nunca limpar a pilha de atividades?
Ruchir Baronia
@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
Hiren Patel
Mas, em algum momento, mostra uma tela branca enquanto chama novas atividades. Ho para resolver isso?
Sagar
4

No meu caso, o LoginActivity também foi fechado. Como um resultado,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

não ajudou.

No entanto, a configuração

Intent.FLAG_ACTIVITY_NEW_TASK

me ajudou.

Prashant Gami
fonte
Estou fazendo o usuário executar muitas atividades, uma após a outra, através de intenções. Preciso fazer alguma coisa para garantir que o aplicativo não trava com muitas atividades na pilha? Obrigado!
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
fonte
1
por que você está usando os dois this.finish()e setFlags()também para limpar a atividade atual?
Sagar
3

Observei que você pediu uma solução que não depende finish(), mas me pergunto se isso pode ajudar.

Rastreei se um sinalizador de saída é gerado com uma variável de classe estática, que sobrevive a vida útil do aplicativo inteiro. Em cada atividade relevanteonResume() , use

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

A classe ExitHelper

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

Digamos que em mainActivity, um usuário pressione um botão para sair - você pode definir ExitHelper.isExitFlagRaised = true;e depois finish(). Depois disso, outras atividades relevantes retomadas automaticamente também serão concluídas.

Kevin Lee
fonte
o que acontecerá se eu usar o código em MainActivity onresume () e voltar à mainatividade a partir da 2ª atividade onbackpress
Mithu
3

Esta decisão funciona bem:

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

Mas novas atividades são lançadas por muito tempo e você vê a tela branca em algum momento. Se isso for crítico, use esta solução alternativa:

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();
    }
}

Como usá-lo:

public class ActivityA extends BaseActivity {

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

Desvantagem: todas as atividades que devem ser fechadas na pilha devem estender BaseActivity

maXp
fonte
2

Para Xamarin Developers, você pode usar:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
BYISHIMO Audace
fonte
1

Usando o Kotlin:

Você pode definir o sinalizador diretamente usando o método setter. No Kotlin oré o substituto para o Java bit a bit ou |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Se você planeja usá-lo regularmente, crie uma função de extensão Intent

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

Você pode chamar diretamente essa função antes de iniciar a intenção

intent.clearStack()
Gibolt
fonte