十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
Android Startup提供一种在应用启动时能够更加简单、高效的方式来初始化组件。开发人员可以使用Android Startup来简化启动序列,并显式地设置初始化顺序与组件之间的依赖关系;

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:空间域名、网页空间、营销软件、网站建设、金台网站维护、网站推广。
今天我们就来聊聊
使用 AndroidX App Startup 来运行所有依赖项的初始化有两种方式:
手动初始化(也是延迟初始化);
在 build.gradle 文件内添加依赖;
- implementation "androidx.startup:startup-runtime:1.0.0-alpha01"
 
实现 Initializer 接口,并重写两个方法,来初始化组件;
- public class MvpInitializer implements Initializer
 { - @NonNull
 - @Override
 - public Void create(@NonNull Context context) {
 - MvpManager.init(context);
 - return null;
 - }
 - @NonNull
 - @Override
 - public List
 >> dependencies() { - return new ArrayList<>();
 - }
 - }
 - ......
 - }
 
create(Context): 这里进行组件初始化工作;
dependencies(): 返回需要初始化的列表,同时设置 App 启动时依赖库运行的顺序;
在 AndroidManifest.xml 文件中注册 InitializationProvider;
- android:authorities="${applicationId}.androidx-startup"
 - android:name="androidx.startup.InitializationProvider"
 - android:exported="false"
 - tools:node="merge" >
 
App 启动的时 App Startup 会读取 AndroidManifest.xml 文件里面的 InitializationProvider 下面的 声明要初始化的组件,完成自动初始化工作;
2、手动初始化(也是延迟初始化)
在 build.gradle 文件内添加依赖;
创建一个类 LibaryD 实现 Initializer 接口,并重写两个方法,来初始化组件;
在 AndroidManifest.xml 文件中注册 InitializationProvider
- android:name="androidx.startup.InitializationProvider"
 - android:authorities="${applicationId}.androidx-startup"
 - android:exported="false"
 - tools:node="merge">
 - android:name="com.test.Initializer"
 - android:value="androidx.startup"
 - tools:node="remove" />
 
在AndroidManifest文件中配置的组件名必须为androidx.startup.InitializationProvider,现在我们来看这个类的源码;
- InitializationProvider.java
 - public final class InitializationProvider extends ContentProvider {
 - @Override
 - public boolean onCreate() {
 - Context context = getContext();
 - if (context != null) {
 - 初始化
 - AppInitializer.getInstance(context).discoverAndInitialize();
 - } else {
 - throw new StartupException("Context cannot be null");
 - }
 - return true;
 - }
 - @Override
 - public Cursor query(...) {
 - throw new IllegalStateException("Not allowed.");
 - }
 - @Override
 - public String getType(...) {
 - throw new IllegalStateException("Not allowed.");
 - }
 - @Nullable
 - @Override
 - public Uri insert(...) {
 - throw new IllegalStateException("Not allowed.");
 - }
 - @Override
 - public int delete(...) {
 - throw new IllegalStateException("Not allowed.");
 - }
 - @Override
 - public int update(...) {
 - throw new IllegalStateException("Not allowed.");
 - }
 - }
 
InitializationProvider其实也是利用了 ContentProvider 的启动机制,在ContentProvider#onCreate(...)中执行初始化;
ContentProvider 的其他方法是没有意义的,所以都抛出了IllegalStateException;
App Startup 在 ContentProvider 中调用了AppInitializer#discoverAndInitialize()执行自动初始化;
AppInitializer是 App StartUp 框架的核心类,整个 App Startup 框架的代码其实非常少,其中很大部分核心代码都在 AppInitializer 类中;
2.1.AppInitializer.java discoverAndInitialize
- final Set
 >> mDiscovered; - void discoverAndInitialize() {
 - 获取 androidx.startup.InitializationProvider 组件信息
 - ComponentName provider = new ComponentName(mContext.getPackageName(), InitializationProvider.class.getName());
 - ProviderInfo providerInfo = mContext.getPackageManager().getProviderInfo(provider, GET_META_DATA);
 - androidx.startup 字符串
 - String startup = mContext.getString(R.string.androidx_startup);
 - 获取组件信息中的 meta-data 数据
 - Bundle metadata = providerInfo.metaData;
 - 遍历 meta-data 数据
 - if (metadata != null) {
 - Set
 > initializing = new HashSet<>(); - Set
 keys = metadata.keySet(); - for (String key : keys) {
 - String value = metadata.getString(key, null);
 - 判断 meta-data 数据中,value 为 androidx.startup 的键值对
 - if (startup.equals(value)) {
 - Class> clazz = Class.forName(key);
 - 检查指定的类是 Initializer 接口的实现类
 - if (Initializer.class.isAssignableFrom(clazz)) {
 - Class extends Initializer>> component = (Class extends Initializer>>) clazz;
 - 将 Class 添加到 mDiscovered Set 中
 - mDiscovered.add(component);
 - 初始化此组件
 - doInitialize(component, initializing);
 - }
 - }
 - }
 - }
 - }
 - mDiscovered 用于判断组件是否已经自动启动
 - public boolean isEagerlyInitialized(@NonNull Class extends Initializer>> component) {
 - return mDiscovered.contains(component);
 - }
 
2.2.AppInitializer.java AppInitializer.java
- private static final Object sLock = new Object();
 - 缓存每个组件的初始化结果;
 - final Map
 , Object> mInitialized; - 初始化此组件
 T doInitialize(Class extends Initializer>> component, Set > initializing) { - 对 sLock 加锁
 - Object result;
 - 判断 initializing 中存在当前组件,说明存在循环依赖
 - if (initializing.contains(component)) {
 - String message = String.format("Cannot initialize %s. Cycle detected.", component.getName());
 - throw new IllegalStateException(message);
 - }
 - 检查当前组件是否已初始化
 - if (!mInitialized.containsKey(component)) {
 - 当前组件未初始化
 - 记录正在初始化
 - initializing.add(component);
 - 通过反射实例化 Initializer 接口实现类
 - Object instance = component.getDeclaredConstructor().newInstance();
 - Initializer> initializer = (Initializer>) instance;
 - 遍历所依赖的组件
 - List
 >> dependencies = initializer.dependencies(); - if (!dependencies.isEmpty()) {
 - for (Class extends Initializer>> clazz : dependencies) {
 - 如果所依赖的组件未初始化,递归执行初始化
 - if (!mInitialized.containsKey(clazz)) {
 - doInitialize(clazz, initializing); 注意:这里将 initializing 作为参数传入
 - }
 - }
 - }
 - 初始化当前组件
 - result = initializer.create(mContext);
 - 移除正在初始化记录
 - initializing.remove(component);
 - 缓存初始化结果
 - mInitialized.put(component, result);
 - } else {
 - 当前组件已经初始化,直接返回
 - result = mInitialized.get(component);
 - }
 - return (T) result;
 - }
 
手动初始化(懒加载)的源码分析:
- AppInitializer.java
 - public
 T initializeComponent(@NonNull Class extends Initializer > component) { - 调用 doInitialize(...) 方法:
 - return doInitialize(component, new HashSet
 >()); - }
 
其实非常简单,就是调用上一节的doInitialize(...)执行初始化。需要注意的是,这个方法是允许在子线程调用的,换句话说,自动初始化与手动初始化是存在线程同步问题的,那么 App Startup 是如何解决的呢?
前面有一个sLock没有说吗?其实它就是用来保证线程同步的锁:
T doInitialize(Class extends Initializer>> component, Set > initializing) { - 对 sLock 加锁
 - synchronized (sLock) {
 - ...
 - }
 - }
 
App Startup 是 Jetpack 的新成员,是为了解决因 App 启动时运行多个 ContentProvider 会增加 App 的启动时间的问题;
使用了一个 InitializationProvider 管理多个依赖项,消除了每个库单独使用 ContentProvider 成本,减少初始化时间;
App Startup 允许你自定义组件初始化顺序;
App Startup 提供了一种延迟初始化组件的方法,减少 App 初始化时间;