我估计百分之90的人做具体项目的时候,都会有A(登录界面) —> B(主界面) —> A(退出登录)。我想说明的是这个并不是很难,而且有很多实现方式,我只是写了我以前写的方式,及另外一种方式。。当然可能有更好的方式,大家可以留言。谢谢。
这里的B(主界面)我是笼统的讲了。比如微信,登录后,先是一个主界面,但是要在<我> —> <设置> —> <退出按钮> .这个时候,这个B界面也就有二级深度了。一个有四个Tab的主界面,然后一个设置的界面。有二个界面。
有这么几个需求:
在A(登录界面) 处直接按返回按钮是直接退出整个应用。
当A(登录界面) —> B(主界面)后,在B(主界面) 上不能直接返回退到A(登录界面)。且在B界面双击返回就要退出整个应用。即退出B界面和A界面。
当在B界面点击“退出登录”按钮后,需要回到A界面。这时候,在这个A界面处直接按返回键是会退出整个应用。
我的思路
B界面中的退出按钮就一级深度
那太简单了。 A(登录界面) —> B(主界面) 的时候,把A给finish掉,然后B(主界面) —> A(退出登录)的时候,把先启动A(登录界面),然后把B(主界面)给finish掉即可。B界面中的退出按钮在很多级深度界面里面
如果想要像第一种情况那样处理的话,那么在B(主界面) —> A(退出登录)的时候,启动了A(登录界面)后,把那些打开的界面都要关闭,如果有二级深度,那要把二个Activity都要关闭。如果更多,也都要关闭。只留一个A登录界面。
我那时候觉得这样比较麻烦,我就想到了Activity的启动方式,如果把Activity的启动方式设置为"singleTask",然后启动这个Activity的时候,会把这个Activity上面的Activity都会给推出栈。这样就剩这一个了。
所以我想到了把A(登录界面)的启动方式设置"singleTask"不就好了。在登录到B(主界面)的时候,先不把A(登录界面)关闭,然后在退出登录的时候把A(登录界面)重新启动,这样A(登录界面)就把上面的所有的B所包含的Activity都关闭了。(PS:这里把A设为singleTask后面会有另外一个坑,等会后面解说)
好,我们就一步步来:
第一步
先在AndroidManifest.xml中把这个A(登录界面)设置为"singleTask"
<activity
android:name=".modules.view.activity.LoginActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
我们既然要退出登录的时候再次启动这个栈底的A,所以这时候在A这个Activity中调用startActivity的时候,不去调用finish()方法。
第二步
我们这时候已经启动了B(主界面),这时候如果你点击返回按钮,会发现,返回到了A界面,这样是有问题的。一般在主界面,都是点击返回会提示“请连续点击返回二次退出应用”。这种我想大家都是家常饭了。复写onKeyDown方法。执行自己的方法:
long SystemTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
if(System.currentTimeMillis()- SystemTime < 1000 && SystemTime != 0){
Intent intent = new Intent();
intent.setAction("ExitApp");
intent.setClass(HomePageActivity.this,LoginActivity.class);
startActivity(intent);
}else{
SystemTime = System.currentTimeMillis();
Toast.makeText(aty, "双击返回按钮进行退出", Toast.LENGTH_SHORT).show();
}
}
return false;
}
这时候大家发现我不仅重新startActivity了A(登录界面)这个Activity。而且还对intnet设置了 intent.setAction("ExitApp");
为什么添加这个Action,因为在B(主界面)上双击返回的时候,要退出整个程序,要关闭所有的Activity,所以就是先启动了A(登录界面)这个Activity,然后再把A(登录界面)的Activity 给finish()即可。当时退出登录的时候,就单纯的启动A(登录界面)这个Activity即可,所以我要做个标记,判断这次启动A(登录界面)这个Activity是‘关闭应用’还是‘退出登录’。
第三步
对应的我们在“退出登录”这个按钮的点击事件也是启动A(登录界面)这个Activity即可。
Intent intent = new Intent();
intent.setClass(getActivity(),LoginActivity.class);
startActivity(intent);
第四步
然后我们知道,重新startActivity 一个已经启动的并且启动模式为"singleTask"的Activity。是会调用onNewIntent()方法。所以我们在A(登录界面)复写onNewIntent()方法
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if ("ExitApp".equals(intent.getAction())) {
finish();
System.exit(0);
}
}
好了,这里要开启另外一个大坑了。不知道大家遇到过没有,请注意,前方高能!!!!!
按照上面写的,测试了下发现没有问题。完美的实现了我们的需求,然后这时候在B(主界面)的时候,我按钮home键,回到了桌面,然后我点击这个app的图标进入,而不是按了menu键在后台列表中选择这个app进入,你会发现,B(主界面)不见了!!!!,变为了A(登录界面)了!!!!而且如果还是刚才那样,在B(主界面)的时候,按home键回到了桌面,按了menu键在后台列表中选择这个app进入,就没问题!!!!
后来发现了这个问题的原因。
因为我们的A是登录界面,登录界面一般来说肯定是启动页,而启动页的启动方式直接设置成"singleTask",这时候你最小化应用后,并且已点击桌面图标的形式再次进入,就会重新回到启动界面。
所以我们这里对A不能设置为"singleTask",要设置为"singleTop",然后我们再把所有startActivity 这个A(登录界面)的intent都多加一句:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
然后就OK了!!!!
后记:我觉得用RxBus也可以,每个界面都启动的时候订阅一个事件,内容是finish(),点击"退出登录"按钮,向所有订阅的Activity发送,然后Activity都执行了finish方法。不过自己没写。哈哈。