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),非常感谢大家看到这里!

相关推荐
消失的旧时光-19431 小时前
kotlin的密封类
android·开发语言·kotlin
服装学院的IT男2 小时前
【Android 13源码分析】WindowContainer窗口层级-4-Layer树
android
CCTV果冻爽4 小时前
Android 源码集成可卸载 APP
android
码农明明4 小时前
Android源码分析:从源头分析View事件的传递
android·操作系统·源码阅读
秋月霜风5 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教5 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python
编程乐学7 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
problc8 小时前
Android中的引用类型:Weak Reference, Soft Reference, Phantom Reference 和 WeakHashMap
android
IH_LZH8 小时前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
去看全世界的云8 小时前
【Android】Handler用法及原理解析
android·java