Android 退出应用程序和返回桌面

1、结束进程

  • KillProcess():
    可以杀死当前应用活动的进程,这一操作将会把所有该进程内的资源(包括线程全部清理掉)。当然,由于ActivityManager时刻监听着进程,一旦发现进程被非正常Kill,它将会试图去重启这个进程。
android.os.Process.killProcess(android.os.Process.myPid());
  • System.exit():
    Java中结束进程的方法,调用它将关闭当前的JVM虚拟机。
//正常退出
System.exit(0);
//非正常退出
System.exit(1);

KillProcess() 和 System.exit(),许多人都使用过,当你栈里只有一个Activity的时候,这个措施是行之有效的。但当关闭多个Activity的时候,栈里有多个Activity时,这两个方法就不起作用了。
因为通过杀进程方式退出,会被系统认为异常退出,会保存应用的一些状态信息比如Activity运行栈,然后会恢复这个应用。当恢复一个Android应用程序时,会先从栈里面移除异常的Activity,相当于Back键操作。

2、容器式

自定义一个Actiivty栈,通过单例模式的Activity栈来管理所有Activity,创建一个Activity管理类来实现

public class AppManager {

    private Stack<WeakReference<Activity>> mActivityStack;
    private static volatile AppManager mInstance;

    private AppManager() {

    }

    public static AppManager getInstance() {
        if (mInstance == null) {
            synchronized (AppManager.class) {
                if (mInstance == null) {
                    mInstance = new AppManager();
                }
            }
        }
        return mInstance;

    }

    /**
     * 添加Activity到堆栈
     * @param activity activity实例
     */
    public void addActivity(Activity activity) {
        if (mActivityStack == null) {
            mActivityStack = new Stack<>();
        }
        mActivityStack.add(new WeakReference<>(activity));
    }

    /**
     * 检查弱引用是否释放,若释放,则从栈中清理掉该元素
     */
    public void checkWeakReference() {
        if (mActivityStack != null) {
            for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                WeakReference<Activity> activityReference = it.next();
                Activity temp = activityReference.get();
                if (temp == null) {
                    it.remove();// 使用迭代器来进行安全的加锁操作
                }
            }
        }
    }

    /**
     * 获取当前Activity
     * @return 当前(栈顶)activity
     */
    public Activity currentActivity() {
        checkWeakReference();
        if (mActivityStack != null && !mActivityStack.isEmpty()) {
            return mActivityStack.lastElement().get();
        }
        return null;
    }

    /**
     * 结束除当前activtiy以外的所有activity
     * @param activtiy 不需要结束的activity
     */
    public void finishOtherActivity(Activity activtiy) {
        if (mActivityStack != null && activtiy != null) {
            for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                WeakReference<Activity> activityReference = it.next();
                Activity temp = activityReference.get();
                if (temp == null) {
                    // 清理掉已经释放的activity
                    it.remove();
                    continue;
                }
                if (temp != activtiy) {
                    // 使用迭代器来进行安全的加锁操作
                    it.remove();
                    temp.finish();
                }
            }
        }
    }

    /**
     * 结束除指定activtiy 集合以外的所有activity
     * @param cls 指定的某类activity
     */
    public void finishOtherActivity(Class<?> cls) {
        if (mActivityStack != null) {
            for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                WeakReference<Activity> activityReference = it.next();
                Activity activity = activityReference.get();
                if (activity == null) {
                    // 清理掉已经释放的activity
                    it.remove();
                    continue;
                }
                if (!activity.getClass().equals(cls)) {
                    // 使用迭代器来进行安全的加锁操作
                    it.remove();
                    activity.finish();
                }
            }
        }
    }

    /**
     * 结束当前Activity
     */
    public void finishActivity() {
        Activity activity = currentActivity();
        if (activity != null) {
            finishActivity(activity);
        }
    }

    /**
     * 结束指定的Activity
     * @param activity 指定的activity实例
     */
    public void finishActivity(Activity activity) {
        if (activity != null) {
            for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                WeakReference<Activity> activityReference = it.next();
                Activity temp = activityReference.get();
                if (temp == null) {
                    // 清理掉已经释放的activity
                    it.remove();
                    continue;
                }
                if (temp == activity) {
                    it.remove();
                }
            }
            activity.finish();
        }
    }

    /**
     * 结束指定类名的所有Activity
     * @param cls 指定的类的class
     */
    public void finishActivity(Class<?> cls) {
        if (mActivityStack != null) {
            for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                WeakReference<Activity> activityReference = it.next();
                Activity activity = activityReference.get();
                if (activity == null) {
                    // 清理掉已经释放的activity
                    it.remove();
                    continue;
                }
                if (activity.getClass().equals(cls)) {
                    it.remove();
                    activity.finish();
                }
            }
        }
    }

    /**
     * 结束所有Activity
     */
    public void finishAllActivity() {
        if (mActivityStack != null) {
            for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                WeakReference<Activity> activityReference = it.next();
                Activity activity = activityReference.get();
                if (activity != null) {
                    activity.finish();
                }
            }
            mActivityStack.clear();
        }
    }

    /**
     * 退出应用程序
     */
    public void exitApp() {
        try {
            finishAllActivity();
            // 从操作系统中结束掉当前程序的进程
            android.os.Process.killProcess(android.os.Process.myPid());
        } catch (Exception e) {
            Log.e("Exit exception", e.getMessage());
        }

    }
}

使用方式:

  • 在BaseActivity#onCreate回调中添加AppManager.getInstance().addActivity(this)
  • 获取当前栈顶activityAppManager.getInstance().currentActivity()
  • 销毁当前activity:调用AppManager.getInstance().finishActivity()->可在BaseActivity#onDestroy添加
  • 销毁指定activity:调用AppManager.getInstance().finishActivity(XXX.class)
  • 销毁指定activity集合:调用AppManager.getInstance().finishActivity(Class<Activity> cls)
  • 结束除当前activtiy以外的所有activity:调用AppManager.getInstance().finishOtherActivity(XXX.class)
  • 结束除当前activtiy集合以外的所有activity:调用AppManager.getInstance().finishOtherActivity(Class<Activity> cls)
  • 结束所有activity:调用finishAllActivity()
  • 退出应用调用AppManager.getInstance().exitApp()

在BaseActivity基类中添加引用,把所有Activity存储起来,Activity销毁的时候移除栈

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //移除当前Activity
        AppManager.getInstance().finishActivity(this);
    }
}

如果activityStack持有Activity的强引用,当某个Activity异常退出时,activityStack没有及时释放掉引用,可能会导致内存问题。

退回系统桌面,不退出应用

Android应用开发中,有一种场景,就是我们不希望用户直接按Back键退出Activity,而是希望应用隐藏到后台的假退出,类似于按Home键的效果。

方法一:

    public void onBackHome(Activity activity) {
        if (activity != null) {
            Intent home = new Intent(Intent.ACTION_MAIN);
            home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            home.addCategory(Intent.CATEGORY_HOME);
            activity.startActivity(home);
        }
    }

方法二:

    public void onBackgroud(Activity activity, boolean isTaskRoot) {
        if (activity != null) {
            activity.moveTaskToBack(false);
        }
    }

moveTaskToBack()方法:在activity中调用 moveTaskToBack (boolean nonRoot)方法即可将activity 退到后台,不是finish()退出activity。
参数说明:
参数为false——代表只有当前activity是task根,指应用启动的第一个activity时,才有效;
参数为true——则忽略这个限制,任何activity都可以有效。
说明:判断Activity是否是task根,Activity本身给出了相关方法:isTaskRoot()

moveTaskToBack调用后,task中activity的顺序不会发生变化,例如A启动B,B中调用此方法退到后台,重新启动应用会调用B中的onRestart-onStart-onResume方法,不会重新调用onCreate,而且在B中按下back键返回的还是A,这就是退到后台的功能。类似于系统home键效果。

参考:
一招搞定Android Activity的管理
android常见技巧---Android按返回键退出程序但不销毁

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352