Android Application创建流程

我们在进行应用开发的时候,在程序初始化或者引用第三方的一些库的时候,都要求进行一些初始化工作。而这些初始化工作一般都要求传入一个上下文,为了不引起内存泄漏,传入的上下文会是一个ApplicationContext,而初始化工作我们一般都会放入Application的onCreate里面。但其实一直以来我都不明白这个Application是在时候进行创建的,onCreate又是在什么时候进行调用的。今天就带着这些疑惑来深入学习下Application的创建过程。
首先,我们要明确我们APP程序整个程序的入口点在ActivityThread里面的main()方法。
ActivityThread从命名上看是一个线程,但你仔细看它的继承关系的话,将其理解为一个handler更为合适。

//ActivityThread.java
public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        //实例话ActivityThread 执行其内部函数attach
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
private void attach(boolean system, long startSeq) {
	//获取到的是ActivityManagerService的接口,不太清楚的可以去看下关于AMS、PMS部分的介绍
	final IActivityManager mgr = ActivityManager.getService();
            try {
            //执行attachApplication方法 
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
}

执行attach方法的时候首先获取到ActivityManagerService的接口,然后调用attachApplication方法,参数传入了mAppThread。这个参数需要特别注意下,类是ApplicationThread为ActivityThread的内部类,嗯,其实可以理解为ActivityThread与AMS通信的一个桥梁,后续AMS的相关回调将通过这个mAppThread进行。

//ActivityManagerService.java
@Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            //也就这句看着还像是比较关键吧
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
//ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
  //这前面有一堆的判断、数据整理、收集类的工作
    if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (instr2 != null) {
            //关键在这 thread前面说了这是一个ApplicationThread,数据的回调会通过它。看到这么多的参数了么,是否那么熟悉
                thread.bindApplication(processName, appInfo, providers,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
            }
}

这里看到通过ApplicationThread.bindApplication进行回调进行信息的相关数据回去

//ActivityThread.java
public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, AutofillOptions autofillOptions,
                ContentCaptureOptions contentCaptureOptions) {
            if (services != null) {
                if (false) {
                    // Test code to make sure the app could see the passed-in services.
                    for (Object oname : services.keySet()) {
                        if (services.get(oname) == null) {
                            continue; // AM just passed in a null service.
                        }
                        String name = (String) oname;

                        // See b/79378449 about the following exemption.
                        switch (name) {
                            case "package":
                            case Context.WINDOW_SERVICE:
                                continue;
                        }

                        if (ServiceManager.getService(name) == null) {
                            Log.wtf(TAG, "Service " + name + " should be accessible by this app");
                        }
                    }
                }

                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);
			//将数据组织为一个AppBindData 
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            data.buildSerial = buildSerial;
            data.autofillOptions = autofillOptions;
            data.contentCaptureOptions = contentCaptureOptions;
            //发送消息出去
            sendMessage(H.BIND_APPLICATION, data);
        }

bindApplication这个方法也很清晰,将收到的数据组装为AppBindData,然后 sendMessage(H.BIND_APPLICATION, data)将数据给发出去。这里需要注意一下的是H是一个继承于Handler的ActivityThread的内部类。

case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    //直接看消息处理部分,也就只有这句代码对我们有用了吧
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
private void handleBindApplication(AppBindData data) {
//关键的2句代码
	Application app;
    app = data.info.makeApplication(data.restrictedBackupMode, null);
}
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
    //关键代码
   app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
}
public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Application) cl.loadClass(className).newInstance();
    }

ok,看到这其实我们明白了绕了那么大一圈其实最后通过ClassLoader用反射的形式去实例化了一个Application。what…why,直接new Application不就行了嘛,何必多此一举呢?其实我们想一下我们继承Application的时候有统一的命名么,答案是没有,随您高兴。那作为系统又怎么知道您的名字叫什么呢?所以要求你在xml中配置.name属性,然后嘛,我就只有用反射来实例化了咯。好了,创建了,而且在newApplication中调用了attach方法,那么Application的onCreate又是什么时候调用的呢?我们顺着handleBindApplication方法往下找会找到如下代码。

try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                      "Unable to create application " + app.getClass().getName()
                      + ": " + e.toString(), e);
                }
            }
public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

看到了么,先创建Application,然后通过mInstrumentation.callApplicationOnCreate(app)实现Application的onCreate方法的调用。至此,我们不在迷茫Application到底是何时创建,怎么被创建的了吧。ok,代码还是比较好追的,这就打完收工了哦!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值