我们平常在项目开发中,会引入或多或少第三方sdk,引入时基本上都需要初始化,而大部分sdk初始化,都提倡在 Application的onCreate()里面初始化,比如下面:
class MyApplication:Application() {
override fun onCreate() {
super.onCreate()
MySdk().init(this)
MySdk1().init(this)
MySdk2().init(this)
MySdk3().init(this)
Log.d("MyTest", "MyApplication create")
}
}
这样,随着项目开发,引入的第三方sdk肯定会越来越多,这样就会让Application里面做初始化的代码非常多非常臃肿,而且太多也会影响整个App的启动效率。那有没有一种方案,既可以让 Application不那么臃肿,又提高App的启动效率呢?
有
Jetpack 的 AppStartup
怎么用呢?很简单,就三步
1.引入依赖
2.实现 Initializer 接口
3.在AndroidManifest.xml的注册
【1.引入依赖】
dependencies {
implementation "androidx.startup:startup-runtime:1.0.0-alpha02"
}
【2.实现 Initializer 接口】
class SdkInitializer : Initializer<Any> {
override fun create(context: Context) {
// init your sdk
MySdk().init(context)
Log.d("MyTest", "Initializer create")
}
override fun dependencies(): List<Class<out Initializer<*>>> {
Log.d("MyTest", "Initializer dependencies")
return emptyList()
}
}
【3.在AndroidManifest.xml的注册】
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.leo.dicaprio.myutilapp.startup.SdkInitializer"
android:value="androidx.startup" />
</provider>
这里主要一下,AndroidManifest.xml注册的内容,只有 meta-data - name 可以更改,其他的地方最好不要改,也不需要改
就是这么简单。把需要初始化的sdk,都放在 Initializer 的 create() 和 dependencies() 两个接口里面,具体放在哪个接口里呢?
如果你引入的sdk1,是不需要依赖其他的sdk2,那只需要把sdk1放进 create() 初始化即可,如下:
class SdkInitializer : Initializer<Any> {
override fun create(context: Context) {
// init your sdk
MySdk1().init(context)
Log.d("MyTest", "Initializer create")
}
override fun dependencies(): List<Class<out Initializer<*>>> {
Log.d("MyTest", "Initializer dependencies")
// 如果没有需要初始化的sdk,返回 空列表即可
return emptyList()
}
}
如果你引入的sdk1,是需要依赖其他的sdk2,那需要把sdk2 放进 dependencies() 里面,再把sdk1放进 create() 初始化,
因为 dependencies() 先于 create() 回调,保证sdk2 先初始化, 如下:
【SdkInitializer 】
class SdkInitializer : Initializer<Any> {
override fun create(context: Context) {
// init your sdk
MySdk().init(context)
Log.d("MyTest", "Initializer create")
}
override fun dependencies(): List<Class<out Initializer<*>>> {
Log.d("MyTest", "Initializer dependencies")
return listOf(Sdk2Initializer::class.java)
}
}
【SdkInitializer2 】
class Sdk2Initializer : Initializer<Any> {
override fun create(context: Context) {
// init your sdk
MySdk2().init(context)
Log.d("MyTest", "Initializer create2")
}
override fun dependencies(): List<Class<out Initializer<*>>> {
Log.d("MyTest", "Initializer dependencies2")
return emptyList()
}
}
注意,只需要注册一个Initializer , Sdk2Initializer 不需要 在AndroidManifest.xml 注册了,否则会报错...
启动应用,我们看下日志:
/MyTest: Initializer dependencies
/MyTest: Initializer dependencies2
/MyTest: Initializer create2
/MyTest: Initializer create
看日志可得:先去初始化sdk2,再去初始化 sdk1
【原理】
上面只是说到如何使用,但是,它为啥能提高启动效率呢?先看下 Initializer 在 AndroidManifest.xml的注册,
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.leo.dicaprio.myutilapp.startup.SdkInitializer"
android:value="androidx.startup" />
</provider>
其实,Initializer 就是一个 ContentProvider 。而 ContentProvider 的执行,是先于 Application的,流程如下:
一个应用程序的执行顺序是这个样子的。首先调用Application的attachBaseContext()方法,然后调用ContentProvider的onCreate()方法,接下来调用Application的onCreate()方法
我们把 sdk 的初始化 挪到 ContentProvider里面,先于Application,这样只是避免了 Application代码的臃肿,并没有看到提高啥效率了,因为该花多少时间去初始化,还得花多少时间。
然而,你们可记得?上面说过只需要注册一个 Initializer,不需要也不能注册多个 Initializer。其实AppStartup 之所以能提高效率正是在这里,不管你需要初始化多少个sdk,都只需要注册一个 Initializer(即:一个ContentProvider)。
很简单,注册的 ContentProvider 越多,ContentProvider启动 占用的时间就越多。但是只注册一个 ContentProvider,当然可以提高效率。
以上如有问题请留言指出,谢谢