Android:优化应用程序启动时间之App Startup

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情

相信大家在开发中避免不了使用三方库,按照接入文档操作都是在Application的onCreate方法中初始化。甚至有些三方库为了更早的拿到上下文对象Context,会在Manifest中注册ContentProvider。如果不深入了解该库,你也不知道该库是否使用了这种方式。这样就会形成一个什么问题呢,多个Provider在应用启动时同时初始化,本来只是几个很轻量的三方库初始化,到此时则变成了多个重量级Provider初始化,严重浪费资源引起初始化过程变长。

使用Application初始化:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        A.init(this)
        B.init(this)
        C.init(this)
        ......
    }
   
}

使用ContentProvider初始化:

class MyProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        context?.let {
            A.init(it)
        }
        return true
    }
}

正当老铁们在苦恼的时候,Google发力了,在Jetpack中推出了一个小工具App Startup,以下是它的简单说明:

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

说干就干,马上动起来试试效果如何。首先,引入到项目:

dependencies {
    implementation "androidx.startup:startup-runtime:1.1.1"
}

需要实现initializer 接口的类来定义每个组件初始化式。这个接口定义了两个重要的方法,create和dependencies。create内相当于初始化组件的一些相关操作,dependencies内返回的是一个集合,用于设置初始化顺序。

// Initializes WorkManager.
class LitePalInitializer : Initializer<Unit> {
    override fun create(context: Context) {
        A.init(this)
        B.init(this)
        C.init(this)
        ......
    }
    override fun dependencies(): List<Class<out Initializer<*>>> {
        // No dependencies on other libraries.
        return emptyList()
    }
}

接下来是在Manifest中配饰provider:

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

到这里基本就完成了startup的接入,是不是很简单。它会合并其它三方库的provider,减少资源浪费,大大提升应用启动速度。有的同学说我如果我的需求是在某个时间手动初始化其中的一个组件该怎么办呢?其实startup也提供了方法:

单个组件不需要自动初始化在标签中添加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.example.LitePalInitializer"
              tools:node="remove" />
</provider>

禁用所有自动初始化:

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    tools:node="remove" />
</provider>

总结

startup的库使用还是比较简单,相当于把初始化任务放在一个队列中有序的初始化,这个过程是个同步过程,如有异步初始化其实还是无法监听到状态,但这种需求应该不多。合并了其他三方库的Provider初始化,如果应用中三方库使用Provider初始化的比较多,那么恭喜你这个库多少还是有点帮助,反之可能优化程度还是不大,只能借助延迟初始化方案。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情