最近在看Android10里面SystemUI关于手势导航部分,里面使用了dagger依赖注入,一时间找不到dagger初始化实例化的地方,这才有了今天这篇对AppComponentFactory这部分的讲解,AppComponentFactory是Android9加入的,先来整体看下这个类的:

public class AppComponentFactory {

    public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl,
            @NonNull ApplicationInfo aInfo) {
        return cl;
    }

    public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Application) cl.loadClass(className).newInstance();
    }

    public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity) cl.loadClass(className).newInstance();
    }

    public @NonNull BroadcastReceiver instantiateReceiver(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (BroadcastReceiver) cl.loadClass(className).newInstance();
    }

    public @NonNull Service instantiateService(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Service) cl.loadClass(className).newInstance();
    }

    public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (ContentProvider) cl.loadClass(className).newInstance();
    }

    public static final AppComponentFactory DEFAULT = new AppComponentFactory();
}

主要有六个方法和一个指向自己的变量,六个方法包括一个方法是提供类加载器,一个是创建Application,例外四个是创建Android的四大组件,如果你对插件化有了解,那么现在就可以在这里去做一些处理了。说了这么多,那这个类要怎么用呢?只需要在清单文件中配置一下,这里直接看下SystemUI中的配置:

<application
        tools:replace="android:appComponentFactory"
        android:appComponentFactory=".SystemUIAppComponentFactory">
    </application>

这样配置以后,系统在创建Application和四大组件时就会调用到这里配置的这个类,如果没有配置,那么就会直接使用上面类内部定义的DEFAULT变量。下面就来看下这个类在源码中的使用,在之前android10 launcher启动流程一文中有说到,在进程创建后会调用ActivityThread的attach(),接着就会调用到ActivityManagerService.attachApplication()——>attachApplicationLocked(),在attachApplicationLocked()又会调用到ActivityThread.ApplicationThread.bindApplicaiton(),这里就先从这里来看:

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) {
            ... ...

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

这里主要就是赋值,然后通过handler发送消息,最终调用到的是ActivityThread.handleBindApplication():

private void handleBindApplication(AppBindData data) {
        ... ...
        //创建LoadedApk
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
        ... ...
        mInstrumentation = new Instrumentation();
        mInstrumentation.basicInit(this);
        ... ...
        Application app;
        try {
            //创建Application
            //data.info的类型是LoadedApk
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            ... ...
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    //创建ContentProvide
                    installContentProviders(app, data.providers);
                }
            }
            ... ...
            try {
                //调用Application的onCreate()方法
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                ... ...
            }
        } finally {
            ... ...
        }
        ... ...
    }

简化了一下这个方法,从代码顺序可以看到,Application对象最先创建,接着创建ContentProvide,最后才是调用Application的onCreate()方法,这也就是为什么通常说ContentProvide比Application先执行,这里先来看下LoadedApk.makeApplication()创建Application:

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        //如果已经创建了Application,就直接返回
        if (mApplication != null) {
            return mApplication;
        }
        ... ...
        try {
            ... ...
            //创建Application的Context
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //通过Instrumentation创建Application
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ... ...
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        ... ...
        return app;
    }

对于Application的创建又转到了Instrumentation.newApplication():

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;
    }

    private AppComponentFactory getFactory(String pkg) {
        if (pkg == null) {
            Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
            return AppComponentFactory.DEFAULT;
        }
        if (mThread == null) {
            Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
                    + " disabling AppComponentFactory", new Throwable());
            return AppComponentFactory.DEFAULT;
        }
        LoadedApk apk = mThread.peekPackageInfo(pkg, true);
        // This is in the case of starting up "android".
        if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
        return apk.getAppFactory();
    }

这段代码还是比较简单,先是获取AppComponentFactory创建Application,然后Application的attach()方法,进而调用Application的attachBaseContext(),这也说明attachBaseContext()比ContentProvide先执行,这里我们继续看AppComponentFactory的获取LoadedApk.getAppFactory():

public AppComponentFactory getAppFactory() {
        return mAppComponentFactory;
    }

AppComponentFactory的创建是在LoadedApk的构造函数中调用createAppFactory()创建的:

private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
        if (appInfo.appComponentFactory != null && cl != null) {
            try {
                return (AppComponentFactory)
                        cl.loadClass(appInfo.appComponentFactory).newInstance();
            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
            }
        }
        return AppComponentFactory.DEFAULT;
    }

这里的appInfo.appComponentFactory就是在清单文件Manifest中配置的,如果没有配置,就会直接使用AppComponentFactory类中定义的默认对象。这也就是在SystemUI中看到初始化对象在SystemUIAppComponentFactory的instantiateApplication()中,对于开发者来讲,这个方法可以说是整个进程最先被调用的地方了。