必威体育Betway必威体育官网
当前位置:首页 > IT技术

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

时间:2019-09-09 04:41:09来源:IT技术作者:seo实验室小编阅读:71次「手机版」
 

退出

我们的态度是:每天进步一点点,理想终会被实现。

前言


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

目录


常见的有5中方式:

  • 容器式
  • 便捷式
  • 广播式
  • SingleTask式
  • 进程式

实现方法


1.容器式

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

BaseActivity添加代码:

public abstract class BaseActivity extends APPCompatActivity{
 @Override
 protected void onCreate(Bundle savedinstanceState) {
     super.onCreate(savedInstanceState);
     // 添加Activity到堆栈
     ActivityUtils.getInstance().addActivity(this);
 }

 @Override
 protected void onDestroy() {
     super.onDestroy();
     // 结束Activity&从栈中移除该Activity
     ActivityUtils.getInstance().removeActivity(this);
 }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

创建一个全局工具类:

public class ActivityUtils{

   private ActivityUtils() {
   }

   private static Atycontainer instance = new AtyContainer();
   private static List<Activity> activitys = new ArrayList<Activity>();

   public static ActivityUtils getInstance() {
       return instance;
   }

   public void addActivity(Activity activity) {
       activityStack.add(activity);
   }

   public void removeActivity(Activity activity) {
       activityStack.remove(activity);
   }

   /**
    * 结束所有Activity
    */
   public void finishAllActivity() {
       for (int i = 0, size = activityStack.size(); i < size; i++) {
           if ( != activityStack.get(i)) {
               activityStack.get(i).finish();
           }
       }
       activityStack.clear();
   }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 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中实现如下代码:

private boolean isExit;

  /**
   * 双击返回键退出
   */
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {

      if (keyCode == KeyEvent.KEYCODE_BACK) {
          if (isExit) {
              this.finish();

          } else {
              toast.maketext(this, "再按一次退出", Toast.LENGTH_SHORT).show();
              mIsExit = true;
              new handler().postDelayed(new Runnable() {
                  @Override
                  public void run() {
                      isExit= false;
                  }
              }, 2000);
          }
          return true;
      }

      return super.onKeyDown(keyCode, event);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

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

<activity Android:name=".MainActivity"
           android:launchmode="singleTask">
           <intent-filter>
               <action android:name="android.intent.action.MAIN"/>

               <category android:name="android.intent.category.LAUNCHER"/>
           </intent-filter>
       </activity>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

3.广播式

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

public abstract class BaseActivity extends Activity {

   private static final String ACTION = "action.exit";

   private ExitReceiver exitReceiver = new ExitReceiver();

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       IntentFilter filter = new IntentFilter();
       filter.addAction(ACTION);
       registerreceiver(exitReceiver, filter);
   }

   @Override
   protected void onDestroy() {
       super.onDestroy();
       unregisterReceiver(exitReceiver);
   }

   class ExitReceiver extends BroadcastReceiver {

       @Override
       public void onreceive(context context, Intent intent) {
           BaseActivity.this.finish();
       }

   }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 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"
  • 1

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

private static final String TAG_EXIT = "exit";

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

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

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

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

5.进程式

1.android.os.Process.killProcess(android.os.Process.myPid());

2.System.exit(0);

3.activitymanager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
   manager.killBackgroundProcesses(getPackageName());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

总结


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

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


温馨提示:

我创建了一个技术交流群,群里有各个行业的大佬都有,大家可以在群里畅聊技术方面内容,以及文章推荐;如果有想加入的伙伴加我微信号【luotaosc】备注一下“加群”

另外关注公众号,还有一些个人收藏的视频

回复“Android” ,获取Android视频链接。

回复“java” ,获取Java视频链接。

回复“C++” ,获取C++视频链接。

回复“C” ,获取C视频链接。

回复“Python” ,获取Python视频链接等等。

原创文章不易,如果觉得写得好,扫码关注一下点个赞,是我最大的动力。

关注我,一定会有意想不到的东西等你:

每天专注分享Android、JAVA干货

这里写图片描述

备注:程序圈LT

        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
            </p>

相关阅读

传360退出北京时间 360:不予置评

A5创业网(公众号:iadmin5)4月21日消息,昨日360已退出&ldquo;北京时间&rdquo;,第一批股权转让款已到账的消息热传,360回应此事称:不予置

苹果回应夸大续航:不同测试方式可能产生不同的结果

A5创业网(公众号:iadmin5)5月5日讯,近日有关媒体对苹果报道的部分苹果产品电池续航时间产生较大误差被疯传,不过苹果回应夸大续航事

电商品牌运营是什么?品牌运营方式有哪些?

在电商行业中,品牌运营往往被称为是一门&ldquo;玄学&rdquo;,一方面它的地位和权重越来越高;另一方面,似乎它又很模糊,看起来,少有人能够

为什么你爱用的 App,都用卡片式设计?

今天这篇文章,将全面介绍「卡片式设计」,看完之后,你会知道为什么爱用的 app 都喜欢用这样的设计。网页和手机 app 逐渐摈弃了传统单

seo关键词优化怎样推广 seo关键词优化推广方式

seo关键词优化一直是公司企业网站一项非常重要的内容,而今天排企来公司的seo技术人员给大家列举一下关于seo关键词优化推广的方式:s

分享到:

栏目导航

推荐阅读

热门阅读