sky*_*ler 228 android activity-lifecycle android-lifecycle
我的应用程序中的所有活动都要求用户登录才能查看.用户几乎可以从任何活动中注销.这是应用程序的要求.在用户注销的任何时候,我都想将用户发送到Login Activity.此时我希望此活动位于历史堆栈的底部,以便按"后退"按钮可将用户返回到Android的主屏幕.
我已经看到这个问题问了几个不同的地方,都回答了类似的答案(我在这里概述),但我想在这里提出收集反馈.
我已经尝试通过设置其Intent标志来打开Login活动,FLAG_ACTIVITY_CLEAR_TOP这似乎是在文档中概述的,但是没有实现我将Login活动放在历史堆栈底部并阻止用户导航回来的目标以前看到的登录活动.我也尝试使用android:launchMode="singleTop"清单中的Login活动,但这也没有完成我的目标(并且似乎无论如何都没有效果).
我相信我需要清除历史堆栈,或者完成之前打开的所有活动.
一种选择是让每个活动onCreate检查登录状态,finish()如果没有登录.我不喜欢这个选项,因为后退按钮仍可供使用,当活动靠近时自动导航.
下一个选项是维护LinkedList对所有可以从任何地方静态访问的开放活动的引用(可能使用弱引用).注销时,我将访问此列表并迭代所有先前打开的活动,并finish()在每个活动上进行调用.我很快就会开始实施这种方法.
但是,我宁愿使用一些Intent标志技巧来实现这一目标.我很高兴发现我可以满足我的应用程序的要求,而不必使用我上面概述的两种方法中的任何一种.
有没有办法通过使用Intent或清单设置来实现这一点,或者是我的第二个选择,保持已LinkedList打开的活动是最佳选择?或者我还有另一种选择吗?
Fra*_*ita 208
我可以建议你另一种方法恕我直言更强大.基本上,您需要向需要保持登录状态的所有活动广播注销消息.因此,您可以在所有Actvities中使用sendBroadcast并安装BroadcastReceiver.像这样的东西:
/** on your logout method:**/
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_LOGOUT");
sendBroadcast(broadcastIntent);
Run Code Online (Sandbox Code Playgroud)
接收者(安全活动):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**snip **/
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.package.ACTION_LOGOUT");
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive","Logout in progress");
//At this point you should start the login activity and finish this one
finish();
}
}, intentFilter);
//** snip **//
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*ass 148
一个新的Android程序员花了一天时间研究这个问题并阅读所有这些StackOverflow线程似乎是一种成熟的仪式.我现在是新成立的,我离开这里看看我的谦逊经历,以帮助未来的朝圣者.
首先,根据我的研究,没有明显或直接的方法可以做到这一点(as of September 2012).你认为你可以简单startActivity(new Intent(this, LoginActivity.class), CLEAR_STACK)而不是.
你可以做startActivity(new Intent(this, LoginActivity.class))用FLAG_ACTIVITY_CLEAR_TOP-这将导致框架向下搜索堆栈,找到LoginActivity的你早期的原始实例,重新创建和清除(向上)堆栈的其余部分.由于Login可能位于堆栈的底部,因此您现在有一个空堆栈,Back按钮就会退出应用程序.
但是 - 这只有在您之前在堆栈底部保留原始LoginActivity实例时才有效.如果像许多程序员一样finish(),LoginActivity一旦用户成功登录就选择了它,那么它就不再位于堆栈的基础上而且FLAG_ACTIVITY_CLEAR_TOP语义不适用......最终你会LoginActivity在现有堆栈的基础上创建一个新的.这几乎肯定不是你想要的(用户可以"退回"登录前一个屏幕的奇怪行为).
因此,如果您以前使用finish()过LoginActivity,那么您需要寻求一些机制来清理堆栈,然后开始新的LoginActivity.看起来@doreamon这个帖子的答案是最好的解决方案(至少对我不起眼的看法):
我强烈怀疑你是否将LoginActivity保持活着这一棘手的问题导致了很多这种混乱.
祝好运.
tha*_*h84 114
UPDATE
超级finishAffinity()方法将有助于减少代码但实现相同.它将完成当前活动以及堆栈中的所有活动,getActivity().finishAffinity()如果您在片段中,则使用它.
finishAffinity();
startActivity(new Intent(mActivity, LoginActivity.class));
Run Code Online (Sandbox Code Playgroud)
原始答案
假设LoginActivity - > HomeActivity - > ... - > SettingsActivity调用signOut():
void signOut() {
Intent intent = new Intent(this, HomeActivity.class);
intent.putExtra("finish", true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // To clean up all activities
startActivity(intent);
finish();
}
Run Code Online (Sandbox Code Playgroud)
HomeActivity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean finish = getIntent().getBooleanExtra("finish", false);
if (finish) {
startActivity(new Intent(mContext, LoginActivity.class));
finish();
return;
}
initializeView();
}
Run Code Online (Sandbox Code Playgroud)
这对我有用,希望它对你也有帮助.:)
xba*_*esx 71
如果您使用的是API 11或更高版本,您可以尝试这样做:FLAG_ACTIVITY_CLEAR_TASK- 它似乎正在解决您遇到的问题.显然,前API 11的人群将不得不使用一些组合,让所有活动检查额外的,如@doreamon建议,或其他一些技巧.
(另请注意:要使用此功能,您必须传入FLAG_ACTIVITY_NEW_TASK)
Intent intent = new Intent(this, LoginActivity.class);
intent.putExtra("finish", true); // if you are checking for this in your other Activities
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_CLEAR_TASK |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
Run Code Online (Sandbox Code Playgroud)
小智 30
我也花了几个小时...同意FLAG_ACTIVITY_CLEAR_TOP听起来像你想要的:清除整个堆栈,除了正在启动的活动,所以Back按钮退出应用程序.然而正如Mike Repass所提到的,FLAG_ACTIVITY_CLEAR_TOP仅在你正在启动的活动已经在堆栈中时起作用; 当活动不存在时,旗帜不做任何事情.
该怎么办?使用FLAG_ACTIVITY_NEW_TASK将正在启动的活动放入堆栈,这使得该活动成为历史堆栈上新任务的开始.然后添加FLAG_ACTIVITY_CLEAR_TOP标志.
现在,当FLAG_ACTIVITY_CLEAR_TOP用于在堆栈中查找新活动时,它将存在并在其他所有清除之前被拉起.
这是我的退出功能; View参数是函数附加的按钮.
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();
}
Run Code Online (Sandbox Code Playgroud)
很多答案.也许这个也会有所帮助 -
Intent intent = new Intent(activity, SignInActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
this.finish();
Run Code Online (Sandbox Code Playgroud)