前几天 Google 更新了几个 Jetpack 新成员 Hilt、Paging 3、App Startup 等等,周末空闲时间实践了一下 App Startup 可以前去查看 GitHub 上的项目 AndroidX-Jetpack-Practice ,接下来一起来分析一下 AndroidX App Startup。
通过这篇文章你将学习到以下内容:
来自 Google 文档: App Startup 是 Android Jetpack 最新成员,提供了在 App 启动时初始化组件简单、高效的方法,无论是 library 开发人员还是 App 开发人员都可以使用 App Startup 显示的设置初始化顺序。
简单的说就是 App Startup 提供了一个 ContentProvider 来运行所有依赖项的初始化,避免每个第三方库单独使用 ContentProvider 进行初始化,从而提高了应用的程序的启动速度。
无论是 Google 提供的库还是第三方库,启动时运行一些初始化逻辑并不少见,例如 WorkManager 在应用启动时使用 ContentProvider 进行初始化,来看一下 Google 工程师 Husayn Hakeem 分享的一张的图。
上图表示现在我们有三个库分别 LibraryA、LibraryB、和 LibraryC 它们使用自己的 ContentProviders 进行初始化。
而 App Startup 提供了一个 ContentProvider 来运行所有依赖项的初始化(LibraryA、LibraryB、和 LibraryC),如下图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kLCB646r-1597795791932)(http://cdn.51git.cn/2020-06-13-15919794525048.jpg)]
刚才我们说到无论是 Google 提供的库还是第三方库,App 启动运行时会初始化一些逻辑,它们为了方便开发者使用,避免开发者手动调用,使用 ContentProvider 进行初始化,例如 WorkManager 在应用启动时使用 ContentProvider 进行初始化,我们来看一下 WorkManager 的源码,先来看一下 AndroidManifest.xml 文件内容。
如上所见,我们可以看到在 AndroidManifest.xml 文件内定义了一个名为 WorkManagerInitializer 的 ContentProvider,我来看看 WorkManagerInitializer 里面都做了什么。
public class WorkManagerInitializer extends ContentProvider {
@Override
public boolean onCreate() {
// Initialize WorkManager with the default configuration.
WorkManager.initialize(getContext(), new Configuration.Builder().build());
return true;
}
......
// 省略了没用的代码
}
如上所见其实就是在 WorkManagerInitializer 的 onCreate() 方法里面,使用默认配置初始化 WorkManager。
我们也来模仿 WorkManager 写一个 Demo,这里只贴出部分代码,更多信息查看 GitHub 上的 AppStartupSimple 下面的 ContentProvider 模块。
class WorkContentProvider : ContentProvider() {
override fun onCreate(): Boolean {
Log.d(TAG, "WorkContentProvider create()")
return true
}
.....
}
com.hi.dhl.startup.simple D/WorkContentProvider: WorkContentProvider create()
假设你的 App 有很多类似于 WorkManager 这样的库,都在 ContentProvider 里面进行一些初始化工作,在 App 启动时运行多个 ContentProvider,这样会带来一些问题:
private void handleBindApplication(AppBindData data) {
......
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
// 创建ContentProvider
installContentProviders(app, data.providers);
}
}
......
try {
// 调用调用 Application 的 OnCreate 方法
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
......
}
这是在 App 冷启动时自动运行初始化的,这样只会增加 App 的加载时间,用户希望 App 加载得快,启动慢会带来糟糕的用户体验,AndroidX App Startup 正是为了解决这个问题而出现的。
使用 AndroidX App Startup 来运行所有依赖项的初始化有两种方式:
具体可以查看 GitHub 上的 AppStartupSimple 下面的 Startup-Library 模块相关代码。
implementation "androidx.startup:startup-runtime:1.0.0-alpha01"
class LibaryC : Initializer {
override fun create(context: Context): Dependency {
// 初始化工作
Log.e(TAG, "init LibaryC ")
return Dependency()
}
override fun dependencies(): MutableList>> {
return mutableListOf(LibaryB::class.java)
}
......
}
正如 GitHub 上的 AppStartupSimple 示例项目,它依赖结构就是 LibaryC 依赖于 LibaryB,LibaryB 依赖于 LibaryA,输出结果如下所示:
com.hi.dhl.startup.simple E/LibaryA: init LibaryA
com.hi.dhl.startup.simple E/LibaryB: init LibaryB
com.hi.dhl.startup.simple E/LibaryC: init LibaryC
App 启动的时 App Startup 会读取 AndroidManifest.xml 文件里面的 InitializationProvider 下面的
声明要初始化的组件,完成自动初始化工作。
只需要在
标签内添加 tools:node="remove"
清单合并工具会将它从清单文件中删除。
AppInitializer.getInstance(context).initializeComponent(MyInitializer::class.java)
如果组件初始化之后,再次调用 AppInitializer.initializeComponent() 方法不会再次初始化。
手动初始化(也是延迟初始化)是非常有用的,组件不需要在 App 启动时运行,只需要在需要它地方运行,可以减少 App 的启动时间,提高启动速度。
这篇文章主要介绍了以下内容:
声明要初始化的组件。全文到这里就结束了,神奇宝贝 (PokemonGo) 基于 Jetpack + MVVM + Repository + Data Mapper + Kotlin Flow 的实战项目,我也正在为 PokemonGo 项目设计更多的场景,也会加入更多的 Jetpack 成员,在 PokemonGo 项目首页增加了更新记录,可以点击下方链接前往查看 PokemonGo 项目的更新记录。
PokemonGo GitHub 地址:https://github.com/hi-dhl/PokemonGo
致力于分享一系列 Android 系统源码、逆向分析、算法、翻译、Jetpack 源码相关的文章,正在努力写出更好的文章,如果这篇文章对你有帮助给个 star,文章中有什么没有写明白的地方,或者有什么更好的建议欢迎留言,欢迎一起来学习,在技术的道路上一起前进。
正在建立一个最全、最新的 AndroidX Jetpack 相关组件的实战项目 以及 相关组件原理分析文章,目前已经包含了 App Startup、Paging3、Hilt 等等,正在逐渐增加其他 Jetpack 新成员,仓库持续更新,可以前去查看:AndroidX-Jetpack-Practice, 如果这个仓库对你有帮助,请仓库右上角帮我点个赞。
由于 LeetCode 的题库庞大,每个分类都能筛选出数百道题,由于每个人的精力有限,不可能刷完所有题目,因此我按照经典类型题目去分类、和题目的难易程度去排序。
每道题目都会用 Java 和 kotlin 去实现,并且每道题目都有解题思路、时间复杂度和空间复杂度,如果你同我一样喜欢算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:Leetcode-Solutions-with-Java-And-Kotlin,一起来学习,期待与你一起成长。
正在写一系列的 Android 10 源码分析的文章,了解系统源码,不仅有助于分析问题,在面试过程中,对我们也是非常有帮助的,如果你同我一样喜欢研究 Android 源码,可以关注我 GitHub 上的 Android10-Source-Analysis,文章都会同步到这个仓库。
目前正在整理和翻译一系列精选国外的技术文章,不仅仅是翻译,很多优秀的英文技术文章提供了很好思路和方法,每篇文章都会有译者思考部分,对原文的更加深入的解读,可以关注我 GitHub 上的 Technical-Article-Translation,文章都会同步到这个仓库。