美文网首页Android资源收录Android 经典笔记Android杂识
Android 经典笔记之二:如何退出应用程序

Android 经典笔记之二:如何退出应用程序

作者: 杨充211 | 来源:发表于2017-08-15 18:39 被阅读67次

    目录介绍:
    1.如何退出应用程序
    1.1 第一种方式:以任务栈形式退出程序
    1.2 第二种方式:任务管理器方法【简称:进程式】
    1.3 第三种方式:跳转页面后销毁栈堆【SingTask式】
    1.4 第四种方式:容器式退出程序【目前用的就是这种 】
    1.5 第五种方式:广播式退出程序
    1.6 第六种方式:懒人式退出程序

    第一种方式:以任务栈形式退出程序

    • 1.思路分析:
      在Android的Activity中,当有多个Activity多次跳转后,点击返回或退出按钮会发现它会出现循环,会将刚刚打开的Activity,打开了多少次,一次次返回回去,当回到最开始的Activity后才会回到桌面
      想要应用程序完全退出,可定义一个栈,利用单列模式管理Activity,写一个自定义Application类。
      在每个Activity的onCreate()方法中调用自定义Application.getInstance().addActivity(this);方法,将该Activity添加到ExitApplication实例中,在要退出的地方调用自定义Application.getInstance().exit();方法,从而将整个应用程序完全退出。

    • 2.首先自定义Application类

    public class App extends Application {
        private List<Activity> activityList = new LinkedList<>();
        private static App instance;
    
        public App() {
    
        }
    
        // 单例模式中获取唯一的ExitApplication实例
        public static App getInstance() {
            if (null == instance) {
                instance = new App();
            }
            return instance;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    
        // 将Activity添加到容器中
        public void addActivity(Activity activity) {
            activityList.add(activity);
        }
    
        // 当要退出Activity时,遍历所有Activity 并finish
        public void exit() {
            for (Activity activity : activityList) {
                activity.finish();
            }
            System.exit(0);
        }
    }
    
    • 3.在父类BaseActivity中添加继承子类Activity到栈中【注意是所有Activity中必须添加】
    //将该Activity添加到自定义Application实例中,
    public class BaseActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 添加Activity到堆栈
            App.getInstance().addActivity(this);     //这句话必须添加
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 结束Activity&从栈中移除该Activity
            //App.getInstance().removeActivity(this);          //这句话建议不添加,因为有时返回上一个Activity不希望被销毁
        }
    }
    
    
    • 4.在主页面执行退出程序方法
    // 物理返回键,双击退出
    private long exitTime = 0;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(MainActivity.this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                App.getInstance().exit();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    

    第二种方式:任务管理器方法

    • 2.1 方法比较简单,但不太好使用
    // 物理返回键,双击退出
    private long exitTime = 0;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(MainActivity.this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                //系统会将,该包下的 ,所有进程,服务,全部杀掉,就可以杀干净了,要注意加上权限
                //<uses-permission android:name="android.permission.RESTART_PACKAGES"/>
                ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);
                am.restartPackage(getPackageName());
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    

    第三种方式:历史栈销毁所有Activity

    • 3.1 思路:通过Intent的Flags来控制堆栈去解决
      Android的窗口类提供了历史栈,我们可以通过stack的原理来巧妙的实现,这里我们在A窗口打开B窗口时在Intent中直接加入标 志 Intent.FLAG_ACTIVITY_CLEAR_TOP,这样开启B时将会清除该进程空间的所有Activity。
      android中,每打开一个Activity,便会在栈中加入一个Activity,当该Activity被摧毁后,栈中便移除了它,并且栈中的Activity是按照开打的先后顺序依次排排列的。
      Android的窗口类提供了历史栈,我们可以通过stack的原理来巧妙的实现,这里我们在A窗口打开B窗口时在Intent中直接加入标志 Intent.FLAG_ACTIVITY_CLEAR_TOP,这样开启B时将会清除该进程空间的所有Activity。
    Intent intent = new Intent(this,MainActivity.class); 
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
    startActivity(intent);
    

    或者,下面这种方式也可以可以的,简单快捷

    • 1、设置MainActivity的加载模式为singleTask
    • 2、重写MainActivity中的onNewIntent方法
    • 3、需要退出时在Intent中添加退出的tag
    // 物理返回键,双击退出
    private long exitTime = 0;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(MainActivity.this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                exit();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    
    /**退出程序**/
    protected void exit() {
        // 退出程序方法有多种
        // 这里使用clear + new task的方式清空整个任务栈,只保留新打开的Main页面
        // 然后Main页面接收到退出的标志位exit=true,finish自己,这样就关闭了全部页面
        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("exit", true);
        startActivity(intent);
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent != null) {
            boolean isExit = intent.getBooleanExtra("exit", false);
            if (isExit) {
                this.finish();
            }
        }
    }
    

    第四种:容器式退出程序【目前用的就是这种】

    • 建立一个全局容器,把所有的Activity存储起来,退出时循环遍历finish所有Activity
    public class BaseActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 添加Activity到堆栈
            AtyContainer.getInstance().addActivity(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //这句话建议不添加,因为有时返回上一个Activity不希望被销毁
            // 结束Activity&从栈中移除该Activity
            //AtyContainer.getInstance().removeActivity(this);
        }
    }
    
    class AtyContainer {
    
        public AtyContainer() {
        }
    
        private static AtyContainer instance = new AtyContainer();
        private static List<Activity> activityStack = new ArrayList<Activity>();
    
        public static AtyContainer getInstance() {
            return instance;
        }
    
        /**
         * 添加Activity到堆栈
         */
        public void addActivity(Activity activity) {
            if (activityStack == null) {
                activityStack = new ArrayList<Activity>();
            }
            activityStack.add(activity);
        }
    
        /**
         * 移除指定的Activity
         */
        public void removeActivity(Activity activity) {
            if (activity != null) {
                activityStack.remove(activity);
                activity = null;
            }
        }
        /**
        * 结束所有Activity
        */
        public void finishAllActivity() {
            for (int i = 0, size = activityStack.size(); i < size; i++) {
                if (null != activityStack.get(i)) {
                    activityStack.get(i).finish();
                }
            }
            activityStack.clear();
        }
    }
    

    这种方法比较简单, 但是可以看到activityStack持有这Activity的强引用,也就是说当某个Activity异常退出时,activityStack没有即使释放掉引用,就会导致内存问题,接下来我们看一种类似的方式,但是会稍微优雅一点点

    第五种方式:广播式退出程序

    • 通过在BaseActivity中注册一个广播,当退出时发送一个广播,finish退出
    public class BaseActivity extends Activity {
    
        private static final String EXITACTION = "action.exit";
        private ExitReceiver exitReceiver = new ExitReceiver();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            IntentFilter filter = new IntentFilter();
            filter.addAction(EXITACTION);
            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、将MainActivity设置为singleTask
    • 2、将退出出口放置在MainActivity
      我们可以看到很多应用都是双击两次home键退出应用,就是基于这样的方式来实现的,这里在贴一下如何处理连续两次点击退出的源码
        private boolean mIsExit;
        /**
        * 双击返回键退出
        */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (mIsExit) {
                    this.finish();
                } else {
                    Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
                    mIsExit = true;
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mIsExit = false;
                        }
                    }, 2000);
                }
                return true;
            }
            return super.onKeyDown(keyCode, event);
        }
    

    后续:
    平时喜欢写写文章,笔记。别人建议我把笔记,以前写的东西整理,然后写成博客,所以我会陆续整理文章,只发自己写的东西,敬请期待:
    知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
    领英:https://www.linkedin.com/in/chong-yang-049216146/
    简书:http://www.jianshu.com/u/b7b2c6ed9284
    csdn:http://my.csdn.net/m0_37700275
    网易博客:http://yangchong211.blog.163.com/
    新浪博客:http://blog.sina.com.cn/786041010yc
    github:https://github.com/yangchong211
    喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
    脉脉:yc930211
    开源中国:https://my.oschina.net/zbj1618/blog

    相关文章

      网友评论

        本文标题:Android 经典笔记之二:如何退出应用程序

        本文链接:https://www.haomeiwen.com/subject/jipvrxtx.html