随笔博文

Jetpack之—App Startup

2022-12-12 13:21:27 michael007js 91

App Startup库是什么

官方的定义

App Startup库提供了一种在应用程序启动时初始化组件的简单、高效的方法。库开发人员和应用程序开发人员都可以使用App Startup来简化启动顺序并明确设置初始化顺序。App Startup库允许您定义共享单个内容提供程序的组件初始化程序,而不是为您需要初始化的每个组件定义单独的内容提供程序。这可以显着改善应用程序启动时间。

为什么App Startup可以改善应用程序的启动时间呢?

这里就要延伸一下我们一般初始化sdk的方式:

  • 在自定义AppliactiononCreate()方法中初始化sdk,它缺点就是开发者手动调用,优点就是可以自己控制调用时机(这点在国内开发市场很重要哈,现在国内应用市场必须要求用户同意后才能做sdk初始化)

class LiteApp : Application(){
   override fun onCreate() {
       super.onCreate()
       TsApp.get().init(this)
 }
}
  • 在自定义ContentProvideronCreate()中初始化库,这种方式可能不少同学没有用过或者听说过,毕竟我们对于ContentProvider的了解不就是个内容提供者吗?其实,如果大家如果有用过谷歌的Firebase库就知道,使用这个库不用我们自己调用初始化方法就能实现数据分析的上传,其实它就是借用了ContentProvider实现自动调用初始化接口。

ContentProvider的执行时机:

11.png

ContentProvideronCreate()方法是在Appliaction的onCreate()方法之前执行,并且ContentProvider也是四大组件之一,我们可以拿到Context,这里也要记得在AndroidManifest.xml文件中注册一下:

<provider
 android:name=".CustomProvider"
 android:authorities="${applicationId}.customProvider"
 android:exported="false" />

authorities属性没有规定的值,但要保证在整个手机里面的app中是唯一的,以防止和其他应用相冲突。

ContentProvider初始化的优缺点

通过ContentProvider初始化的优点很明显就是不用开发者主动调用sdk的初始化方法,而且初始化比在Application更提前了一点。缺点也很明显,就是增加了额外的耗时消耗,毕竟ContentProvider作为一个四大组件来说还是有不少开销的,如果每个库都搞一个ContentProvider来初始化的话那相当于开了很多Activity一样,这必然会造成较大的耗时开销:

640.png 这是网上找到的一张Google官方给出一个ContentProvider耗时的测试结果,它的这种情况是在空的ContentProvider情况下耗时2ms,当我们在每个ContentProvider里面还有sdk初始化的操作,还有很多个ContentProvider时,这个耗时绝对是值得起重视的,甚至会大大降低了App的启动速度。

那如何解决这个痛点呢?

这就得使用:App Startup。既然是解决,那就是App Startup库可以将所有sdk的初始化用一个ContentProvider来完成,并提高App的启动速度。App Startup库的内部实现了一个ContentProvider,并提供操作标准的方法给开发者,所以对于第三方库来说就不用实现额外的ContentProvider了。当然,这里不能解决的是已经使用ContentProvider进行初始化的第三方库。

App Startup库的使用

添加依赖

dependencies {
 implementation "androidx.startup:startup-runtime:1.1.0-beta01"
}

实现App Startup库的Initializer接口

先创建一个SdkSample模拟sdk,并提供一个init方法:

object SdkSample{
   fun init(context: Context){
       
 }
}

实现Initializer接口

class CustomInitializer:Initializer<Unit> {
   override fun create(context: Context) {
       SdkSample.init(context)
 }

   override fun dependencies(): MutableList<Class<out Initializer<*>>> {
       return mutableListOf()
 }
}
  • create()方法显而易见就是sdk初始化的地方,它提供初始化所需的Context;

  • dependencies()方法表示CustomInitializer是否还需要依赖于其他的Initializer,一般情况下这里都是直接返回空list就行。如果有的话,就在这里进行配置,App Startup会先初始化依赖的Initializer,然后才会初始化当前的CustomInitializer。看下面代码:

class CustomInitializer:Initializer<Unit> {
   override fun create(context: Context) {
       SdkSample.init(context)
 }

   override fun dependencies(): MutableList<Class<out Initializer<*>>> {
       return mutableListOf(FirstInitializer::class.java)
 }
}

//先初始化的FirstInitializer
class FirstInitializer:Initializer<Unit> {
   override fun create(context: Context) {
       SdkSample.init(context)
 }

   override fun dependencies(): MutableList<Class<out Initializer<*>>> {
       return mutableListOf()
 }
}

这个时候CustomInitializer只有在FirstInitializer初始化完了才会开始初始化。

将CustomInitializer配置到AndroidManifest

<provider
 android:name="androidx.startup.InitializationProvider"
 android:authorities="${applicationId}.androidx-startup"
 android:exported="false"
 tools:node="merge">
 <meta-data
     android:name="com.qisan.myapplication.CustomInitializer"
     android:value="androidx.startup" />
</provider>

这个配置里面只有name这个属性是我们能改的,其他都是固定配置,保持这样Startup库才能正常使用。

对于CustomInitializer需要依赖其他Initializer初始化完成才执行的情况,CustomInitializer可以不被声明,只声明FirstInitializer就行了:

<provider
 android:name="androidx.startup.InitializationProvider"
 android:authorities="${applicationId}.androidx-startup"
 android:exported="false"
 tools:node="merge">
 <meta-data
     android:name="com.qisan.myapplication.FirstInitializer"
     android:value="androidx.startup" />
</provider>

到这里,App Startup库的使用就完成了,很简单,三步即可使用:

  • 依赖App Startup的库;

  • 实现一个Initializer;

  • 把实现的Initializer配置到AndroidManifest.xml。

Initializer的动态加载

Initializer都会在App启动时自动执行初始化,但是作为开发者有时候是不需要启动就初始化的,尤其是现在国内应用市场的审核机制,最好在用户同意了你的隐私协议和服务协议才开始初始化,如果你的sdk初始化有涉及http请求或者其他权限,审核的时候都会被驳回来的。要实现动态加载,首先我们要让Initializer不会自动执行,这个时候主要在meta-data 标签中加入 tools:node="remove"即可:

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data
        android:name="com.qisan.myapplication.CustomInitializer"
        android:value="androidx.startup"
        tools:node="remove"/>
</provider>

加上这个节点后在打包成APK时会把所有android:namecom.qisan.myapplication.CustomInitializer的meta-data节点全部删除,这样就无法自动初始化了,要在合适的时机初始化只要调用即可:

AppInitializer.getInstance(this).initializeComponent(CustomInitializer::class.java)
复制代码

小结

从整个使用过程来说,App Startup库的使用非常简单,对于我们一般的应用开发者来说使用了用处好像也不是很大。好像只能把Application里面初始化sdk的代码分离出来。而对于sdk的开发者来说,都用App Startup来实现初始化的确可以提高效率。至于还有其他什么作用,如果大家有好的看法欢迎留言哈.


首页
关于博主
我的博客
搜索