项目需求讨论 -(登录 -> 主界面 -> 退出登录)

4,298 阅读5分钟

我估计百分之90的人做具体项目的时候,都会有A(登录界面) —> B(主界面) —> A(退出登录)。我想说明的是这个并不是很难,而且有很多实现方式,我只是写了我以前写的方式,及另外一种方式。。当然可能有更好的方式,大家可以留言。谢谢。


这里的B(主界面)我是笼统的讲了。比如微信,登录后,先是一个主界面,但是要在<我> —> <设置> —> <退出按钮> .这个时候,这个B界面也就有二级深度了。一个有四个Tab的主界面,然后一个设置的界面。有二个界面。

有这么几个需求:

  1. 在A(登录界面) 处直接按返回按钮是直接退出整个应用。

  2. 当A(登录界面) —> B(主界面)后,在B(主界面) 上不能直接返回退到A(登录界面)。且在B界面双击返回就要退出整个应用。即退出B界面和A界面。

  3. 当在B界面点击“退出登录”按钮后,需要回到A界面。这时候,在这个A界面处直接按返回键是会退出整个应用。

我的思路

  1. B界面中的退出按钮就一级深度
    那太简单了。 A(登录界面) —> B(主界面) 的时候,把A给finish掉,然后B(主界面) —> A(退出登录)的时候,把先启动A(登录界面),然后把B(主界面)给finish掉即可。

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

好了,这里要开启另外一个大坑了。不知道大家遇到过没有,请注意,前方高能!!!!!


按照上面写的,测试了下发现没有问题。完美的实现了我们的需求,然后这时候在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方法。不过自己没写。哈哈。