Android 中几种优雅的退出APP方式介绍

最近由于项目的修改,项目由MainActivity按返回键一次退出修改为MainActivity中连续按两次返回键退出,顺便优化一下推出这里的代码。因此还是在网上搜索了一番,总结比较之后得出了有以下集中方式,优缺点都会提出来,有需要的老铁按需选择。

目录

常见的有5中方式:

  1. 容器式

  2. 便捷式

  3. 广播式

  4. 进程式

  5. SingleTask式

实现方法

1.容器式

容器式可能是我们最常见的方式之一了,主要通过创建一个全局的容器,把所有的Activity都保存下来,退出的时候循环遍历所有activity,然后finish()掉。

BaseActivity添加代码:

  1.  
    public abstract class BaseActivity extends AppCompatActivity{
  2.  
     @Override
  3.  
     protected void onCreate(Bundle savedInstanceState) {
  4.  
         super.onCreate(savedInstanceState);
  5.  
         // 添加Activity到堆栈
  6.  
         ActivityUtils.getInstance().addActivity(this);
  7.  
     }
  8.  
     
  9.  
     @Override
  10.  
     protected void onDestroy() {
  11.  
         super.onDestroy();
  12.  
         // 结束Activity&从栈中移除该Activity
  13.  
         ActivityUtils.getInstance().removeActivity(this);
  14.  
     }
  15.  
     
  16.  
    }

创建一个全局工具类:

  1.  
    public class ActivityUtils{
  2.  
     
  3.  
       private ActivityUtils() {
  4.  
       }
  5.  
     
  6.  
       private static AtyContainer instance = new AtyContainer();
  7.  
       private static List<Activity> activitys = new ArrayList<Activity>();
  8.  
     
  9.  
       public static ActivityUtils getInstance() {
  10.  
           return instance;
  11.  
       }
  12.  
     
  13.  
       public void addActivity(Activity activity) {
  14.  
           activityStack.add(activity);
  15.  
       }
  16.  
     
  17.  
       public void removeActivity(Activity activity) {
  18.  
           activityStack.remove(activity);
  19.  
       }
  20.  
     
  21.  
       /**
  22.  
        * 结束所有Activity
  23.  
        */
  24.  
       public void finishAllActivity() {
  25.  
           for (int i = 0, size = activityStack.size(); i < size; i++) {
  26.  
               if (null != activityStack.get(i)) {
  27.  
                   activityStack.get(i).finish();
  28.  
               }
  29.  
           }
  30.  
           activityStack.clear();
  31.  
       }
  32.  
     
  33.  
    }

这种方式是有一定的缺点的,我们的工具类ActivityUtils持有Activity的引用,当我们的应用发生异常,ActivityUtils持有的引用没有被销毁会导致部分内存问题,而且代码量多,不够优雅,诸多不便。

但是容器式这种方式还是有解决办法的,我们可以采用弱引用的方式,就不存在前面所说的问题了,习惯于容器式的可以采用弱引用这种方式的。

2.便捷式

在之前,先讲一下Activity的启动模式:SingleTask

我们知道Activity有四种加载模式,而singleTask就是其中的一种,使用这个模式之后,当startActivity时,它先会在当前栈中查询是否存在Activity的实例,如果存在,则将其至于栈顶,并将其之上的所有Activity移除栈。我们打开一个app,首先是一个splash页面,然后会finish掉splash页面。跳转到主页。然后会在主页进行N次的跳转,期间会产生数量不定的Activity,有的被销毁,有的驻留在栈中,但是栈底永远是我们的HomeActivity。这样就让问题变得简单很多了。我们只需两步操作即可优雅的实现app的退出。

有了这么一个启动模式,就好办了,我们将退出的出口放在MainActivity中所有事都解决了。

那么这种方法为什么叫便捷式呢?这种方式代码量很少而且很好理解、优雅,而且市面上很多APP都是基于此实现的。我们在MainActivity中实现如下代码:

  1.  
    private boolean isExit;
  2.  
     
  3.  
      /**
  4.  
       * 双击返回键退出
  5.  
       */
  6.  
      @Override
  7.  
      public boolean onKeyDown(int keyCode, KeyEvent event) {
  8.  
     
  9.  
          if (keyCode == KeyEvent.KEYCODE_BACK) {
  10.  
              if (isExit) {
  11.  
                  this.finish();
  12.  
     
  13.  
              } else {
  14.  
                  Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
  15.  
                  mIsExit = true;
  16.  
                  new Handler().postDelayed(new Runnable() {
  17.  
                      @Override
  18.  
                      public void run() {
  19.  
                          isExit= false;
  20.  
                      }
  21.  
                  }, 2000);
  22.  
              }
  23.  
              return true;
  24.  
          }
  25.  
     
  26.  
          return super.onKeyDown(keyCode, event);
  27.  
      }

不要着急,不要以为就完了,还有很重要的一步:将MainActivity设置为singleTask。

  1.  
    <activity android:name=".MainActivity"
  2.  
               android:launchMode="singleTask">
  3.  
               <intent-filter>
  4.  
                   <action android:name="android.intent.action.MAIN"/>
  5.  
     
  6.  
                   <category android:name="android.intent.category.LAUNCHER"/>
  7.  
               </intent-filter>
  8.  
           </activity>

上面这种方法就是我个人认为最简便的方式了,这也符合有些要求按2次退出。

3.广播式

我相信很多的老铁是使用的广播式,毕竟很方便,先上代码,再说利弊。

  1.  
    public abstract class BaseActivity extends Activity {
  2.  
     
  3.  
       private static final String ACTION = "action.exit";
  4.  
     
  5.  
       private ExitReceiver exitReceiver = new ExitReceiver();
  6.  
     
  7.  
       @Override
  8.  
       protected void onCreate(Bundle savedInstanceState) {
  9.  
           super.onCreate(savedInstanceState);
  10.  
           IntentFilter filter = new IntentFilter();
  11.  
           filter.addAction(ACTION);
  12.  
           registerReceiver(exitReceiver, filter);
  13.  
       }
  14.  
     
  15.  
       @Override
  16.  
       protected void onDestroy() {
  17.  
           super.onDestroy();
  18.  
           unregisterReceiver(exitReceiver);
  19.  
       }
  20.  
     
  21.  
       class ExitReceiver extends BroadcastReceiver {
  22.  
     
  23.  
           @Override
  24.  
           public void onReceive(Context context, Intent intent) {
  25.  
               BaseActivity.this.finish();
  26.  
           }
  27.  
     
  28.  
       }
  29.  
     
  30.  
    }

最后再需要退出的地方,发送一个广播就可以了,注意Action和注册的相同就可以了。

但是个人觉得这种方式还是太耗性能,毕竟广播是进程间通信,我们一个退出APP功能不是特别的有必要。

4.SingleTask式

简单解释一下SingleTask这种启动模式的两个特点:

  • 清除堆栈中处于当前Activity上方的Activity

  • 堆栈中含有你要启动的Activity时,不会重新创建。

假设我们的MainActivity是使用的SingleTask的启动模式,假设我跳转到了其他的页面,然后使用startActivity(this,MainActivity.class)的方式再次启动MainActivity,这时MainActivity走到onNewIntent()方法,然后按照生命周期onRestart()——>onStart()——>onResume(),MainActivity不会重新创建。

既然有这么一个特点我们就可以分三步来退出APP:

第一步:MainActivity设置为SingleTask。

android:launchMode="singleTask"

第二步:重写MainActivity中的onNewIntent方法

  1.  
    private static final String TAG_EXIT = "exit";
  2.  
     
  3.  
       @Override
  4.  
       protected void onNewIntent(Intent intent) {
  5.  
           super.onNewIntent(intent);
  6.  
           if (intent != null) {
  7.  
               boolean isExit = intent.getBooleanExtra(TAG_EXIT, false);
  8.  
               if (isExit) {
  9.  
                   this.finish();
  10.  
               }
  11.  
           }
  12.  
       }

第三步:需要退出时在Intent中添加退出的tag

  1.  
    Intent intent = new Intent(this,MainActivity.class);
  2.  
           intent.putExtra(MainActivity.TAG_EXIT, true);
  3.  
           startActivity(intent);

虽然这种方式简单、便捷,但还有弊端:当我们需要退出的时候,假如是在其他的Activity中退出,这时MainActivity要走一段生命周期的方法,有点浪费。

5.进程式

  1.  
    1.android.os.Process.killProcess(android.os.Process.myPid());
  2.  
       
  3.  
    2.System.exit(0);
  4.  
     
  5.  
    3.ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
  6.  
       manager.killBackgroundProcesses(getPackageName());

这三种方式都能够达到杀死进程的效果,直接退出APP,但是这种太暴力了不推荐使用,而且使用体验不好。不知道是不是华为手机问题,我用华为P10 Plus使用这种方式退出的时候要白屏、闪屏一下,反正就是不建议使用这种方式。



总结

        其实严格来说,还有一种方式就是抛异常让APP强制退出,因为感觉用的人不多就没有细说。

        上面的几种方式中,最不推荐的就是最后第五种方式,暴力而且用户体验不好。大家在项目中看着需求、以及自己习惯的方式来选择就好,今天就到这里了。

转载自:https://mp.weixin.qq.com/s/DAeD5YHS9oNYA-wzcHqJEg

总结

        其实严格来说,还有一种方式就是抛异常让APP强制退出,因为感觉用的人不多就没有细说。

        上面的几种方式中,最不推荐的就是最后第五种方式,暴力而且用户体验不好。大家在项目中看着需求、以及自己习惯的方式来选择就好,今天就到这里了。

原文地址:https://www.cnblogs.com/Alex80/p/13965847.html