Jetpack架构组件学习(4)——APP Startup库的使用
最近在研究APP的启动优化,也是发现了Jetpack中的
App Startup库,可以进行SDK的初始化操作,于是便是学习了,特此记录
两种方式初始化SDK
首先,先是讲解了关于SDK的初始化方式,像我们一般使用到百度地图,或者某些开源库的时候,需要我们进行初始化操作
而他们文档给出的大多数为以下方式:
自定义一个Application,在Application对应的生命周期
OnCreate()方法中进行初始化操作
这样一样,一旦项目接入的SDK过多,Application里的初始化逻辑也是多了起来,且代码层面,每次都要去加代码,也是十分繁琐.
针对代码繁琐的问题,有的开源库作者找到了一种比较取巧的方法,那就是通过四大组件中的ContentProvider进行初始化操作
具体怎么做呢?
首先,创建一个ContentProvider类:
package site.starsone.abdemo
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
import com.blankj.utilcode.util.LogUtils
class MyContentProvider: ContentProvider() {
override fun insert(uri: Uri, values: ContentValues?): Uri? {
TODO("Not yet implemented")
}
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? {
TODO("Not yet implemented")
}
override fun onCreate(): Boolean {
context?.let {
LogUtils.d("初始化了...")
}
return true
}
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
): Int {
TODO("Not yet implemented")
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
TODO("Not yet implemented")
}
override fun getType(uri: Uri): String? {
TODO("Not yet implemented")
}
}
PS:上面,因为我们只是为了初始化,所以只给了onCreate()其他的方法直接留空不写即可
之后,还需要在AndroidManifest.xml文件中进行声明
<application ...>
<provider
android:name=".MyContentProvider"
android:authorities="${applicationId}.myProvider"
android:exported="false" />
</application>
authorities在这里并没有固定的要求,填写什么值都是可以的,但必须保证这个值在整个手机上是唯一的,所以通常会使用${applicationId}作为前缀,以防止和其他应用程序冲突。
运行结果如下所示:

关于运行的流程,如下图所示

一个应用程序的执行顺序是这个样子的。首先调用
Application的attachBaseContext()方法,然后调用
ContentProvider的onCreate()方法,接下来调用Application的onCreate()方法。
我们使用上述方法治好,在提供库给别的开发者用的时候,别的开发者就不用再去多写一步初始化的操作了,简化了其他开发者使用库的操作流程。
上面的方法虽然是比较巧妙,但是ContentProvider会增加许多额外的耗时

一个空白的ContentProvider会多出2ms的加载时间,实际项目复杂多一多,加载速度岂不是直接拖慢?
这有什么解决方法呢?
当然有,官方也是发现了开发者通过ContentProvider来取巧进行初始化的步骤,于是进行了进一步的封装,于是就是今天所讲的App Startup:
它可以将所有用于初始化的ContentProvider合并成一个,从而使App的启动速度变得更快。
话说是不是官方已经变相承认了这种取巧方式哈哈
App Startup基本使用
1.引入依赖
使用之前,老惯例了,引入依赖
implementation 'androidx.startup:startup-runtime:1.0.0'
这里需要注意: 如果使用最新的1.1.1版本,要求最低的SDK版本(compileSdk)要求为31
关于已发布版本,可以点击此链接进行查看jetpack各库版本
2.实现Initializer接口
//Java中这个Unit是Void类型
class SdkAInitializer : Initializer<Unit> {
override fun create(context: Context) {
LogUtils.d("Sdk A 初始化")
}
//默认实现方法返回MutableList,将其改为List
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}
3.声明provider
在AndroidManifest.xml文件中声明:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="site.starsone.abdemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AbDemo">
...
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.site.starsone.abdemo.SdkAInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>
注意点:
- 只需要添加对应的meta-data的内容,并更改name属性即可,其他的代码不需要变动
tools:node需要application标签上声明tools的命名空间meta-data里的android:name要输入class全类名(因为App Startup本质上也是通过反射来找到你的这个类)
效果如下图所示:

进阶使用(依赖关系)
我们再添加一个SdkBInitializer的初始化类:
class SdkBInitializer : Initializer<Unit> {
override fun create(context: Context) {
LogUtils.d("Sdk B 初始化")
}
//默认实现方法返回MutableList,将其改为List
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}
代码实际上与SdkAInitializer一样,上面基本使用没有扩展讲解,这里先讲解一下
dependencies()方法是用来说明当前的SdkBInitializer是否需要前置的某个依赖初始化完毕才执行
我们添加了SdkBInitializer,和之前一样,也得声明
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="site.starsone.abdemo.SdkBInitializer"
android:value="androidx.startup" />
<meta-data
android:name="site.starsone.abdemo.SdkAInitializer"
android:value="androidx.startup" />
</provider>
这里就声明了A和B两个SDK的初始化类,本来我以为声明的顺序会影响初始化的顺序,实际上并不影响
以下截图就是上述代码运行的效果:

于是,我们现在要将上面的顺序变更为以下:
SDKA的初始化,需要SDKB初始化完之后才能进行,于是我们取修改SdkAInitializer的代码
class SdkAInitializer : Initializer<Unit> {
override fun create(context: Context) {
LogUtils.d("Sdk A 初始化")
}
//默认实现方法返回MutableList,将其改为List
override fun dependencies(): List<Class<out Initializer<*>>> {
//这里回传依赖项回去
return listOf(SdkBInitializer::class.java)
}
}
运行结果:

PS: 如果项目中的只有两个依赖的初始化,且这两个初始化有先后顺序,在
AndroidManifest.xml文件可以只写一个
如上面的例子,由于SDKA是要在SDKB初始化后才初始化,所以只用声明SDKA即可(因为代码里已经返回了对应的List,会被找到,无需声明)
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="site.starsone.abdemo.SdkAInitializer"
android:value="androidx.startup" />
</provider>
进阶使用(手动初始化)
上面说明的是自动初始化,考虑到还会有手动初始化的需求
1.取消自动初始化
首先,我们得先配置AndroidManifest.xml文件中的属性,取消初始化
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
tools:node="remove"
android:name="site.starsone.abdemo.SdkAInitializer"
android:value="androidx.startup" />
</provider>
tools:node="remove"而不是直接移除这个标签,是为了确保清单合并工具能够移除所有合并文件的这个标签。在meta-data标签中添加
tools:node="remove",是禁止单个组件的自动初始化如果想要禁止所有组件,则是在provider标签上加上属性
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="remove">
<meta-data
android:name="site.starsone.abdemo.SdkAInitializer"
android:value="androidx.startup" />
</provider>
PS: 实际上测试发现,如果你不想你的组件被自动初始化,直接删除对应的
meta-data标签即可
2.代码中进行初始化
至于初始化,则是在代码中进行即可,具体的时机由开发者来定,比如说在点击某个按钮之后
只需要传对应初始化的类即可,代码如下:
AppInitializer.getInstance(this).initializeComponent(SdkBInitializer::class.java)
上述代码是在Activity中进行的,所以使用的this
参考
- Jetpack各库最新版本 | Android 开发者 | Android Developers
- Jetpack各库说明 | Android 开发者 | Android Developers
- Jetpack新成员,App Startup一篇就懂
- Android Jetpack组件之App Startup - 掘金
- App Startup | Android Developers
Jetpack架构组件学习(4)——APP Startup库的使用的更多相关文章
- Jetpack架构组件学习(2)——ViewModel和Livedata使用
要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 原文地址:Jetpack架构组件学习(2)--ViewModel和Livedata使用 | Stars-One ...
- Jetpack架构组件学习(1)——LifeCycle的使用
原文地址:Jetpack架构组件学习(1)--LifeCycle的使用 | Stars-One的杂货小窝 要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 最近 ...
- Jetpack架构组件学习(3)——Activity Results API使用
原文地址:Jetpack架构组件学习(3)--Activity Results API使用 - Stars-One的杂货小窝 技术与时俱进,页面跳转传值一直使用的是startActivityForRe ...
- Jetpack 架构组件 Room 数据库 ORM MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Jetpack 架构组件 LiveData ViewModel MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Jetpack 架构组件 Lifecycle 生命周期 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Android Jetpack 架构组件最佳实践之“网抑云”APP
背景 近几年,Android 相关的新技术层出不穷.往往这个技术还没学完,下一个新技术又出来了.很多人都是一脸黑人问号? 不少开发者甚至开始哀嚎:"求求你们别再创造新技术了,我们学不动了!& ...
- Android 架构:Android Jetpack 架构组件的学习和分析
参考:https://mp.weixin.qq.com/s/n-AzV7Ke8wxVhmC6ruUIUA 参考:https://jekton.github.io/2018/06/30/android- ...
- Jetpack架构组件(二)Lifecycle使用
1.直接添加如下依赖就可以满足日常的工作,如果缺少哪个库,再去单独添加就好了 implementation "android.arch.lifecycle:extensions:1.1.1& ...
随机推荐
- 12.web基础与HTTP协议
web基础与HTTP协议 目录 web基础与HTTP协议 web基础 域名概述 HTML概述 HTML基本标签 HTML语法规则 HTML文件结构 头标签中常用标签 内容标签中常用标签 静态网页与动态 ...
- python基础知识-day8(模块与包、random、os)
1.模块与包 package:相同的模块代码存储在一个目录下(即包里边会包含多个模块). 包不能存储在文件夹的目录下,模块名称不能使用关键字.(不包含工程文件夹) 2.模块与包的实例 1)在工程文 ...
- WPF开发随笔收录-心电图曲线绘制
一.前言 项目中之前涉及到胎儿心率图曲线的绘制,最近项目中还需要添加心电曲线和血样曲线的绘制功能.今天就来分享一下心电曲线的绘制方式: 二.正文 1.胎儿心率曲线的绘制是通过DrawingVisual ...
- linux下怎样在某个文件里面查找一个字符串?
方法一: grep命令 举个栗子:我想要在redis.conf中查询我设置的redis密码,执行下面代码 grep "require" redis.conf #grep " ...
- 项目: ATM+购物车
ATM+购物车 项目文件: 介绍 以下为文件夹层次和内容: readme.md 1. 需求 模拟银行取款 + 购物全过程 1.注册 2.登录 3.提现 4.还款 5.转账 6.查看余额 7.查看购物车 ...
- Template -「矩阵 - 行列式」
#include <cstdio> int Abs(int x) { return x < 0 ? -x : x; } int Max(int x, int y) { return ...
- Note -「模拟退火」
随机化算法属于省选芝士体系 0x01 前置芝士 你只需要会 rand 就可以啦! 当然如果你想理解的更透彻也可以先看看 爬山算法 0x02 关于退火 退火是一种金属热处理工艺,指的是将金属缓慢加热到一 ...
- GIS技术在医疗行业的应用:利用切片地图发布技术解决dmetrix数字病理切片在线浏览
最近一直在研究切片地图发布技术,解决各种矢量和栅格数据的切片地图制作和发布问题.这块的技术在土地评估和调查类公司中应用较多,因为他们经常需要使用各地地图,传统的文件管理方式很难适应工作现状,如果将各种 ...
- Tampermonkey究竟有什么用?
以具体应用实例加以说明. 目标:在youtube页面上观看视频,发现喜欢的视频,单击按钮就可以下载视频. 但是,youtube页面并未提供这样的按钮及其功能. 实现思路:在浏览器下载youtube页面 ...
- Win10系统下安装编辑器之神(The God of Editor)Vim并且构建Python生态开发环境(2020年最新攻略)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_160 众神殿内,依次坐着Editplus.Atom.Sublime.Vscode.JetBrains家族.Comodo等等一众编辑 ...