• 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强制退出,因为感觉用的人不多就没有细说。

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

  • 相关阅读:
    PL/SQL中关于时间的操作
    PL/SQL中关于时间的操作
    Master Data Service调用API创建Model
    ASP.NET Postback回调后参数无效
    Silverlight读取Web.config配置文件
    WCF的用户名+密码认证方式
    Trac 经验谈之(5)插件篇
    Cython 0.15,用 OpenMP 并行多核加速 Python!
    BizTalk Accelerator for HL7医疗行业消息路由处理机制
    Silverlight信息加密 通过Rfc2898DeriveBytes类使用基于HMACSHA1的伪随机数生成器实现PBKDF2
  • 原文地址:https://www.cnblogs.com/Alex80/p/13965847.html
Copyright © 2020-2023  润新知