Android-App应用启动优化(Startup库)

一、问题复现

近期做项目,发现导入了一些第三方库后,应用的启动时间明显延长了,一番捣鼓之后,也是发现了问题所在,在此将解决方法记录下来

在此我也将问题复现下,我们新建个项目,然后直接运行安装到Android设备上,安装成功后,我们需要退出,并将后台给清掉,因为我们需要测试的是应用的冷启动时间

初始启动时间

接着我们调用adb命令去查看应用冷启动的时间:

scss 复制代码
adb shell am start -W (应用包名)/MainActivity

可以看到耗时为

添加第三方库之后的启动时间

这里我们以添加utilcode工具库为例

之后同样是调用adb命令去查看应用的冷启动时间

可以看到应用的启动时间变慢了,我之前这里好奇的是,我只是添加了库,没对库进行初始化,也还没用到它,应用怎么就会变慢了呢?这里我们去通过对应用的的AndroidManifest去进行分析

打开AndroidManifest.xml文件,点击Merged Manifest

通过这里我们可以看到文件里多了个provider

点进去查看发现跳转到了第三方库的AndroidManifest.xml文件

再点进去,可以发现第三方库在此去进行了初始化操作,至此可以发现导致应用启动慢的罪魁祸首就在这里

通过查Android开发者指南可以看到第三方库会在应用启动的时候去进行初始化

二、手动初始化

2.1 移除provider

既然第三方库的自动初始化会导致应用变慢,那就要由我们自己去决定第三方库何时初始化

这就要请到我们今天的主角了------Jetpack之Startup库,现在最新的地址如下:

arduino 复制代码
implementation 'androidx.startup:startup-runtime:1.1.1'

在AndroidManifest.xml中填写如下代码:

xml 复制代码
<!--表示将第三方库utilcode的provider移除掉-->
<provider
    android:name="com.blankj.utilcode.util.UtilsFileProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="remove" />

<!--表示将第三方库startup的provider移除掉,因为我们要自己手动去初始化-->
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="remove" />

再次点击Merged Manifest可以发现provider没有了

2.2 定义组件初始化程序

创建一个实现 Initializer<T> 接口的类

  • create() 方法,其中包含初始化组件并返回 T 实例的所有必要操作。
  • dependencies() 方法,该方法返回初始化程序所依赖的其他 Initializer<T> 对象的列表。您可以使用此方法控制应用在启动时的顺序。

对原先的provider初始化去进行观察

可以发现返回一个boolean值,并且直接返回true

这里我们创建一个UtilCodeInitializer类,并实现Initializer<T>,因为上面的是返回一个boolean值,所以这里的T为Boolean

kotlin 复制代码
class UtilCodeInitializer:Initializer<Boolean> {
    override fun create(context: Context): Boolean {
        Utils.init(context.applicationContext as Application)
        return true

    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }
}

这个类也就代替了provider的初始化功能

2.3延迟初始化

应用原本是一启动第三方库就会初始化,这里我们把它的初始化放到onCreate中执行,并且延迟两秒

为了实现效果的更明显,我这里又添加了一个自定义的provider,并在里面去延迟500ms

scala 复制代码
public class TestProvider extends FileProvider {

    @Override
    public boolean onCreate() {
        //noinspection ConstantConditions
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return true;
    }
}

并在AndroidManifest.xml中去注册

ini 复制代码
<provider
    android:name=".TestProvider"
    android:authorities="${applicationId}.example"
    android:grantUriPermissions="true"
    android:exported="false" />

自动初始化时间

这里的第三方库和我们自定义的provider会在应用启动的时候去初始化

可以看到应用启动时间为800多ms,运行的时候明显感觉慢了一些

延迟初始化

这里我们同样对TestProvider去实现初始化

kotlin 复制代码
class TestProviderInitializer:Initializer<Boolean> {
    override fun create(context: Context): Boolean {
        try {
            Thread.sleep(500)
        } catch (e: InterruptedException) {
            throw RuntimeException(e)
        }
        return true
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }
}

对AndroidManifest.xml中的三个Provider标记去除

在MainActivity的onCreate中去进行延迟2s初始化

ini 复制代码
//这几行代码的作用就代替了之前provider里面的初始化
AppInitializer initializer = AppInitializer.getInstance(MainActivity.this);
initializer.initializeComponent(UtilCodeInitializer.class);
initializer.initializeComponent(TestProviderInitializer.class);

可以看到时间明显缩短了,查看Merged Manifest也是一个provider也没有了

三、总结

这篇文章可能会有点啰嗦,但核心思路是有些第三方库中会注册provider在里面去进行初始化,从而导致拖慢应用的启动,当第三方库非常多的时候,拖慢的会更明显,我们要做的就是将第三方库的provider从AndroidManifest.xml文件中移除,并且实现一个类去接管它的初始化,初始化的时机由我们来定,可以是需要的时候再初始化,也可以延迟一段时间初始化,除了这个功能之外,Startup还有许多的功能,这里我就不再赘述了,有需要的看下官方文档就可以了,应用启动 | Android 开发者 | Android Developers (google.cn),非常感谢大家看到这里!

相关推荐
〆、风神20 分钟前
EasyExcel 数据字典转换器实战:注解驱动设计
android·java·注解
stevenzqzq43 分钟前
Android studio xml布局预览中 Automotive和Autotive Distant Display的区别
android·xml·android studio
QING6181 小时前
Kotlin commonPrefixWith用法及代码示例
android·kotlin·源码阅读
QING6181 小时前
Kotlin groupByTo用法及代码示例
android·kotlin·源码阅读
兰琛7 小时前
Compose组件转换XML布局
android·xml·kotlin
水w8 小时前
【Android Studio】解决报错问题Algorithm HmacPBESHA256 not available
android·开发语言·android studio
隐-梵10 小时前
Android studio进阶教程之(二)--如何导入高德地图
android·ide·android studio
Kika写代码11 小时前
【Android】界面布局-线性布局LinearLayout-例子
android·gitee
wangz7611 小时前
kotlin,jetpack compose,使用DataStore保存数据,让程序下次启动时自动获取
android·kotlin·datastore·jetpack compose
Thread.sleep(0)13 小时前
WebRTC源码解析:Android如何渲染画面
android·webrtc