Limpe toda a pilha do histórico e inicie uma nova atividade no Android
-
28-09-2019 - |
Pergunta
É possível iniciar uma atividade na pilha, limpando todo o histórico anterior?
A situação
Eu tenho uma pilha de atividades que vai A-> B-> C ou B-> C (a tela A seleciona o token do usuário, mas muitos usuários possuem apenas um único token).
Na tela C o usuário poderia executam uma ação que torna a tela B inválida, então o aplicativo deseja levá-los para a tela A, independentemente de ela já estar na pilha.A tela A deve então ser o único item na pilha do meu aplicativo.
Notas
Existem muitas outras perguntas semelhantes, mas não encontrei nada que responda exatamente a essa pergunta.Eu tentei ligar getParent().finish()
- isso sempre resulta em uma exceção de ponteiro nulo. FLAG_ACTIVITY_CLEAR_TOP
só funciona se a atividade já estiver na pilha.
Solução
No nível 11 da API, uma nova bandeira de intenção foi adicionada apenas para isso: INTENT.FLAG_ACTIVO_CLEAR_TASK
Apenas para esclarecer, use isto:
Java
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Kotlin
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
Infelizmente para a API lvl <= 10, ainda não encontrei uma solução limpa para isso. o Solução "Donthackandroidlikethis" é de fato puro hackery. Você não deveria fazer isso. :)
Editar:Conforme @Ben Pearsoncomentário, para API <= 10 agora se pode usar IntentCompat classe para o mesmo. Pode -se usar IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
sinalizador para limpar a tarefa. Assim, você também pode apoiar o nível 11 da API.
Outras dicas
Caso 1: Apenas duas atividades A e B:
Aqui, o fluxo de atividades é A-> b. Tela de aplicação de hospedagem/respingo.
Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();
Caso 2: Mais de duas atividades:
Se houver um fluxo como A-> B-> C-> D-> B e ao clicar no botão de volta na atividade B enquanto vier da atividade D. Nesse caso, devemos usar.
Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
Aqui, a atividade B será iniciada na história de fundo, em vez de uma nova instância por causa de intenção.flag_activity_clear_top e intent.flag_activity_new_task limpa a pilha e o torna o top. Então, quando pressionarmos o botão de volta, todo o aplicativo será encerrado.
Com a versão mais recente do Android> = Uso da API 16 finishAffinity()
A abordagem é adequada para> = API 16.
Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
- É o mesmo que iniciar uma nova atividade e limpar toda a pilha.
- Ou reinicie a MainActivity/Firstativity.
Passei algumas horas também ... e concordo que Flag_Activity_Clear_top soa como o que você deseja: limpe toda a pilha, exceto a atividade que está sendo lançada, para que o botão traseiro sai do aplicativo. No entanto, como Mike Repass mencionou, Flag_Activity_Clear_top só funciona quando a atividade que você está lançando já está na pilha; Quando a atividade não está lá, a bandeira não faz nada.
O que fazer? Coloque a atividade sendo lançada na pilha com flag_activity_new_task, o que torna essa atividade o início de uma nova tarefa na pilha de histórico. Em seguida, adicione o sinalizador flag_activity_clear_top.
Agora, quando FLAG_ACTIVIDE_CLEAR_TOP vai encontrar a nova atividade na pilha, ela estará lá e será puxada antes que tudo seja limpo.
Aqui está minha função de logout; O parâmetro de exibição é o botão ao qual a função é anexada.
public void onLogoutClick(final View view) {
Intent i = new Intent(this, Splash.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
}
Você não deve mudar a pilha.O botão Voltar do Android deve funcionar como em um navegador da web.
Posso pensar em uma maneira de fazer isso, mas é um truque e tanto.
Faça suas atividades
singleTask
adicionando-o aoAndroidManifest
Exemplo:<activity android:name=".activities.A" android:label="@string/A_title" android:launchMode="singleTask"/> <activity android:name=".activities.B" android:label="@string/B_title" android:launchMode="singleTask"/>
Ampliar
Application
que manterá a lógica de para onde ir.
Exemplo:
public class DontHackAndroidLikeThis extends Application {
private Stack<Activity> classes = new Stack<Activity>();
public Activity getBackActivity() {
return classes.pop();
}
public void addBackActivity(Activity activity) {
classes.push(activity);
}
}
De a para B:
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class);
startActivity(this, B.class);
De B a C:
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class);
startActivity(this, C.class);
Em C:
If ( shouldNotGoBackToB() ) {
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.pop();
}
e segure o botão Voltar para pop()
da pilha.
Mais uma vez, você não deveria fazer isso :)
Imediatamente após iniciar uma nova atividade, usando startActivity
, certifique -se de ligar finish()
para que a atividade atual não esteja empilhada atrás da nova.
Experimente isso:
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();
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
Tente o código abaixo,
Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_CLEAR_TASK|
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Para mim Nenhum dos métodos acima não funciona.
Apenas faça isso com limpe toda a atividade anterior:
finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
Eu achei um hack muito simples, basta fazer isso adicionar novo elemento em AndroidManifest
Como:-
<activity android:name=".activityName"
android:label="@string/app_name"
android:noHistory="true"/>
a android:noHistory
Limpará sua atividade indesejada da pilha.
Às vezes, seu emulador Android pode não conectar a ferramenta Eclipse DDMS e pedir que o ADB comece manualmente. Nesse caso, você pode iniciar ou interromper o ADB usando o prompt de comando.