多进程导致 Application 多次执行的问题研究

来源:互联网 发布:lb极速网络 编辑:程序博客网 时间:2024/05/22 06:25

在项目中我们有时会用到多进程,需要在 AndroidManifest 里进行声明 :

        <activity            android:name=".RemoteActivity"            android:process=":remote"/>

启动这个 Activity 后,你的应用就有了两个进程,这时就有问题了,Application 类的生命周期也调用了两次了:

07-13 10:03:40.069 22804 22804 D MyApplication: onCreate07-13 10:03:40.885 22846 22846 D MyApplication: onCreate

至于为什么 Appilication 类的生命周期为什么会被调用两次,我们需要从底层进行分析,重点是看 Appilication 实例是在什么地方创建的,创建后生命周期是如何调用的;Activity 和 Application 都是普通的类,他们是在 ActivityThread 中创建的,并且给予了它们生命周期回调;

具体 Activity 启动流程可以看 Activity的启动流程
这里分析下与 Appilication 相关的内容

AMS 在收到发起者的 startActivity 请求后执行 ActivityStackSupervisor 的 startSpecificActivityLocked 方法

    void startSpecificActivityLocked(ActivityRecord r,            boolean andResume, boolean checkConfig) {        ProcessRecord app = mService.getProcessRecordLocked(r.processName,                r.info.applicationInfo.uid, true);        r.task.stack.setLaunchTime(r);        if (app != null && app.thread != null) {            try {                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0                        || !"android".equals(r.info.packageName)) {                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,                            mService.mProcessStats);                }                realStartActivityLocked(r, app, andResume, checkConfig);                return;            } catch (RemoteException e) {            }        }        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,                "activity", r.intent.getComponent(), false, false, true);    }

这里调用了 AMS 的 getProcessRecordLocked 方法来查是否在 AMS 中有相关的记录(应用的每个进程名字都会记录在 AMS 中),如果没有,返回的 app 为 null, 这时 调用的是 startProcessLocked 方法

private final void startProcessLocked(ProcessRecord app, String hostingType,            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {            ...            if (entryPoint == null) entryPoint = "android.app.ActivityThread";            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +                    app.processName);            checkTime(startTime, "startProcess: asking zygote to start proc");            Process.ProcessStartResult startResult = Process.start(entryPoint,                    app.processName, uid, uid, gids, debugFlags, mountExternal,                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,                    app.info.dataDir, entryPointArgs);            ...}

在这里创建了一个新的进程,并且调用了 ActivityThread 的 main 方法,在 main 方法里创建了 ActivityThread 对象,也就是说每个进程对应了一个 ActivityThread 对象,然后 AMS 会通知 ActivityThread 的 handleLaunchActivity 来启动 Activity:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {        ...        Activity a = performLaunchActivity(r, customIntent);        ...    }

在这里调用 performLaunchActivity 创建了一个 Activity 和 Application

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {        ...        Activity activity = null;        try {            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();            activity = mInstrumentation.newActivity(                    cl, component.getClassName(), r.intent);            ...        } catch (Exception e) {            ...        }        try {            Application app = r.packageInfo.makeApplication(false, mInstrumentation);            ...            if (activity != null) {                ...                if (r.isPersistable()) {                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                } else {                    mInstrumentation.callActivityOnCreate(activity, r.state);                }        return activity;    }

在这里先创建了 Activity 实例,再创建 Appilication 实例,并调用了 Activity 的 onCreate 方法,其中,在 makeApplication 里调用了 Application 的 onCreate 方法:

public Application makeApplication(boolean forceDefaultAppClass,            Instrumentation instrumentation) {            ...            app = mActivityThread.mInstrumentation.newApplication(                    cl, appClass, appContext);            ...            instrumentation.callApplicationOnCreate(app);        return app;    }

总结下,由于创建了新的进程,每个进程会创建自己的 ActivityThread 实例,每个 ActivityThread 又会创建自己的 Application 实例并且会调用它的 onCreate 方法;也就是说每个进程都会有自己的 Appilication 实例,而这个实例都用的同一个类来创建的,所以你在这个类里面写的东西当然会被执行多次;
所以这就是为什么同一个应用多进程会造成 Application 的生命周期方法会调用多次;
解决办法是在 Application 的生命周期方法里对进程名进行判断,如果不是同进程就不要执行一些不必要的东西了

阅读全文
0 0
原创粉丝点击