Android退出应用最优雅的方式

    |     2016年1月7日   |   Activity活动   |     0 条评论   |    1449

退出 Android 应用,常见做法是容器收齐 Activity、广播 finish,或直接杀进程。更稳的是把首页做成 singleTask,再配合退出广播。


一、容器式

建一个全局容器,把所有 Activity 存进去,退出时循环 finish:

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;

public class BaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AtyContainer.getInstance().addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        AtyContainer.getInstance().removeActivity(this);
    }
}

class AtyContainer {
    private AtyContainer() {
    }

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

    public static AtyContainer getInstance() {
        return instance;
    }

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

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

    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 的强引用。某个页面异常退出时如果没及时摘掉引用,就会拖成内存问题。


二、广播式

在 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();
        }
    }
}

三、进程式

直接干掉当前进程,简单粗暴,也“有(wu)效”:

android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
manager.killBackgroundProcesses(getPackageName());

三种都能退出,但模拟器上常弹出 Unfortunately, XXX has stopped;部分真机直接失效,只 finish 当前页(例如小米 Note 一类改过 fw 的 ROM,用这种方式要慎重)。


四、RS 优雅式

RS 即 Receiver + singleTask。Activity 四种启动模式里,singleTask 会在当前栈里找已有实例:找到就把它提到栈顶,并清掉它上面的页面。

打开 App 通常先 Splash,再 finish 掉 Splash 进主页。之后任意跳转,栈底永远是 HomeActivity。退出只需两步:

  1. 只在 HomeActivity 注册退出广播(不必每个页面都注册)。
  2. 把 HomeActivity 的启动模式设为 singleTask。

要退出时先 startActivity(this, HomeActivity.class),再发退出广播:栈里 HomeActivity 之上的页面被清掉,它自己接到广播后再 finish。没有弹框,不用跟机型 ROM 死磕,也没有容器式那份强引用包袱。

方式 做法 代价
容器式 List 收齐 Activity,循环 finish 强引用,异常退出易泄漏
广播式 BaseActivity 注册,发 action.exit 每个页面都要注册/反注册
进程式 killProcess / System.exit / killBackgroundProcesses 模拟器弹框,部分真机失效
RS 式 HomeActivity 设 singleTask + 退出广播 栈底必须是首页

原文出处:小鄧子(@Rx小鄧子)

一句话总结:别杀进程、别用 List 死攥 Activity;把 HomeActivity 设成 singleTask,再发一条退出广播,栈清干净、自己 finish,才是最稳的退法。

转载请注明来源:Android退出应用最优雅的方式
本文链接地址:https://ai.zhousir.top/?p=1113
回复 取消