App Startup原理解析

·  阅读 443

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

前言

在上篇文章中「初始化Library新姿势——App Startup」我们学会了 App Startup 的使用,下面我们接着学习 App Startup 的原理。

切入点

在学习原理之前,我们需要先找到切入点。

因为 ALibraryInitializer 是在 AndroidManifest.xml 中进行注册的,所以我们先看看注册信息:

        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:node="merge">
            <meta-data
                android:name="com.bjsdm.testkotlin.ALibraryInitializer"
                android:value="androidx.startup" />
        </provider>
复制代码

这是一个 ContentProvider,而 ALibraryInitializer 只是 meta-data 里面的值而已,所以我们需要先看看 InitializationProvider

执行流程

我们先来看看 InitializationProvider 源码:

public class InitializationProvider extends ContentProvider {
    @Override
    public final boolean onCreate() {
        Context context = getContext();
        if (context != null) {
            Context applicationContext = context.getApplicationContext();
            if (applicationContext != null) {
                AppInitializer.getInstance(context).discoverAndInitialize();   // <- 重点
            } else {
                StartupLogger.w("Deferring initialization because `applicationContext` is null.");
            }
        } else {
            throw new StartupException("Context cannot be null");
        }
        return true;
    }
}
复制代码

InitializationProvider 的代码也很简单,除了 onCreate() 方法,其它方法都没有具体的实现,而在 onCreate(() 中,最核心的也只是这段:

AppInitializer.getInstance(context).discoverAndInitialize(); 
复制代码

所以我们来看看 discoverAndInitialize() 做了什么:

    void discoverAndInitialize() {
			···
            ComponentName provider = new ComponentName(mContext.getPackageName(),
                    InitializationProvider.class.getName());
            ProviderInfo providerInfo = mContext.getPackageManager()
                    .getProviderInfo(provider, GET_META_DATA);
            Bundle metadata = providerInfo.metaData;
            discoverAndInitialize(metadata);
			···
    }
复制代码

其实也就是获取配置中的 metaData 数据,然后传递给 discoverAndInitialize(metadata)

    void discoverAndInitialize(@Nullable Bundle metadata) {
        String startup = mContext.getString(R.string.androidx_startup);
			···
            if (metadata != null) {
                Set<Class<?>> initializing = new HashSet<>();
                Set<String> keys = metadata.keySet();
                for (String key : keys) {
                    String value = metadata.getString(key, null);
                    if (startup.equals(value)) {
                        Class<?> clazz = Class.forName(key);
                        if (Initializer.class.isAssignableFrom(clazz)) {
                            Class<? extends Initializer<?>> component =
                                    (Class<? extends Initializer<?>>) clazz;
                            mDiscovered.add(component);
  							···
                        }
                    }
                }
                ···
                for (Class<? extends Initializer<?>> component : mDiscovered) {
                    doInitialize(component, initializing);
                }
            }
			···
    }
复制代码

主要作用就是在 metadata 中获取全部的 Initializer 数据,然后存储到 mDiscovered 中,然后对于 mDiscovered 进行遍历,调用 doInitialize

    private <T> T doInitialize(
            @NonNull Class<? extends Initializer<?>> component,
            @NonNull Set<Class<?>> initializing) {
			···
            Object result;
            if (!mInitialized.containsKey(component)) {
                initializing.add(component);
                try {
                	// 创建 Initializer
                    Object instance = component.getDeclaredConstructor().newInstance();
                    Initializer<?> initializer = (Initializer<?>) instance;
                    List<Class<? extends Initializer<?>>> dependencies =
                            initializer.dependencies();
					// 判断是否先初始化 dependencies 的 Initializer
                    if (!dependencies.isEmpty()) {
                        for (Class<? extends Initializer<?>> clazz : dependencies) {
                            if (!mInitialized.containsKey(clazz)) {
                                doInitialize(clazz, initializing);
                            }
                        }
                    }
					···
					// 调用 initializer 的 create(),其实就是对于 initializer 的 SDK 进行初始化
                    result = initializer.create(mContext);
					···
                    initializing.remove(component);
                    mInitialized.put(component, result);
                } 
                ···
            } else {
                result = mInitialized.get(component);
            }
            return (T) result;
        ···
    }
复制代码

主要逻辑:

  • 创建 Initializer
  • 判断是否先初始化 dependencies 的 Initializer
  • 调用 initializer 的 create(),其实就是对于 initializer 的 SDK 进行初始化

至此,initializer 初始化 SDK 的行为就完成了。

分类:
Android
收藏成功!
已添加到「」, 点击更改