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 初始化时间;
分享题目:Android架构进阶之深入理解AppStartup原理
文章起源:http://www.gawzjz.com/qtweb/news49/199099.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联