当前位置: 首页 > news >正文

聊一下Jetpack AppStartUp的使用和原理。

App Startup是Android Jetpack中的一个库,用于在应用启动时初始化组件,能简化启动序列并显式设置初始化依赖顺序,从而提高应用的启动速度。以下是关于App Startup的使用和原理的介绍:

使用方法

  1. 添加依赖:在项目的模块级build.gradle文件中添加对App Startup的依赖。

implementation "androidx.startup:startup-runtime:1.0.0" 

  1. 实现Initializer接口
    • 创建一个类并实现Initializer<T>接口,其中T是要初始化的组件类型。
    • create(Context context)方法中编写初始化组件的逻辑,并返回初始化后的结果。
    • dependencies()方法中返回一个依赖组件的列表,表示当前组件在初始化时所依赖的其他组件。如果当前组件不依赖其他组件,则返回一个空列表。
  2. 配置清单条目
    • 在应用的AndroidManifest.xml文件中,声明一个<provider>元素,指定android:nameandroidx.startup.initializationprovider
    • 设置android:authorities属性为一个全局唯一的值,通常使用${applicationId}.androidx-startup的格式。
    • 设置android:exportedfalse,以限制其他应用访问此组件。
    • 可以使用tools:node="merge"来确保manifest merger tool能够正确解析冲突的节点。
    • <provider>元素内添加<meta-data>子元素,设置android:name为实现了Initializer接口的类的全限定类名,android:value固定为androidx.startup

例如,假设应用依赖于WorkManager并需要在启动时进行初始化,可以这样定义初始化器类WorkManagerInitializer

import androidx.startup.Initializer;
import androidx.work.WorkManager;public class WorkManagerInitializer implements Initializer<WorkManager> {@Overridepublic WorkManager create(Context context) {// 初始化 WorkManager 的逻辑WorkManager.initialize(context, new Configuration.Builder().build());return WorkManager.getInstance(context);}@Overridepublic List<Class<? extends Initializer<?>>> dependencies() {// 没有依赖其他组件,返回空列表return emptyList(); }
}

然后在AndroidManifest.xml中进行配置:

<providerandroid:name="androidx.startup.initializationprovider"android:authorities="${applicationId}.androidx-startup"android:exported="false"tools:node="merge"><meta-dataandroid:name="com.example.WorkManagerInitializer"android:value="androidx.startup" />
</provider>

原理

App Startup的原理主要是利用了ContentProvider在应用启动时会被自动创建和初始化的特性。

当应用启动时,系统会创建并初始化声明在AndroidManifest.xml中的ContentProvider。App Startup中定义了一个特殊的ContentProvider(即InitializationProvider)。在InitializationProvideronCreate方法中,会通过反射机制查找所有在清单文件中配置的<meta-data>标签,其android:name属性对应的类实现了Initializer接口。然后,App Startup会调用这些初始化器的dependencies方法,以确定它们的依赖关系。按照依赖关系的顺序,依次调用每个初始化器的create方法来完成组件的初始化工作。通过这种方式,App Startup可以确保在应用启动时,按照正确的顺序初始化所需的组件,避免了手动在ApplicationonCreate方法中逐个调用初始化方法的繁琐操作,同时也能更好地管理组件之间的依赖关系,提高了应用的启动性能和可维护性。

此外,App Startup还支持手动初始化和延迟初始化。手动初始化可以在特定的时机手动调用初始化方法,适用于初始化成本较高且不一定在应用启动时就需要完成初始化的组件。延迟初始化则可以将某些初始化操作延迟到应用启动后的某个合适时机进行,进一步优化应用的启动速度。

App Startup 为啥可以提高启动速度

一、明确的初始化顺序管理

  1. 依赖关系处理:

    • App Startup 允许开发者明确指定各个初始化器(Initializer)之间的依赖关系。在初始化一个组件时,如果它依赖于其他组件,App Startup 会确保先初始化其依赖的组件。
    • 例如,如果一个网络模块依赖于数据库模块已经初始化完成,通过在网络模块的初始化器中声明对数据库初始化器的依赖,App Startup 会自动按照正确的顺序进行初始化。这样可以避免因依赖关系不明确而导致的错误初始化顺序,减少因错误顺序引起的重复初始化或初始化失败后的重试,从而节省启动时间。
  2. 有序初始化流程:

    • 传统的应用启动过程中,各个组件的初始化可能是分散在不同的地方,没有一个统一的管理机制。这可能导致初始化顺序混乱,尤其是当多个组件之间存在复杂的依赖关系时。
    • App Startup 提供了一个集中管理初始化的方式,使得整个启动过程中的初始化顺序更加清晰和可控。开发者可以根据应用的实际需求,合理安排各个组件的初始化顺序,确保关键组件在需要时已经初始化完成,提高启动效率。

二、异步初始化和延迟加载

  1. 异步初始化:

    • App Startup 支持异步初始化组件。对于一些耗时较长的初始化任务,可以将其放在后台线程中进行,而不会阻塞应用的主线程。
    • 这样,在初始化过程中,主线程可以继续处理其他重要的任务,如显示启动画面、加载基本的用户界面等,不会因为某个耗时的初始化任务而导致整个应用的启动卡顿。
    • 例如,数据库的初始化或者从网络加载一些配置信息等任务可以在后台异步进行,当这些任务完成后,再通知主线程进行相应的处理。
  2. 延迟加载:

    • 并非所有的组件都需要在应用启动的瞬间就完成初始化。App Startup 允许开发者将一些非关键的组件的初始化延迟到应用启动后的某个合适时机进行。
    • 比如,某些功能模块可能只有在用户首次使用该功能时才需要进行初始化。通过延迟加载这些组件,可以减少应用启动时的初始化负担,加快启动速度。

三、减少重复初始化和资源浪费

  1. 单一实例管理:

    • App Startup 确保每个初始化器只会被调用一次,即使在不同的地方引用了同一个初始化器。
    • 这避免了重复初始化同一个组件的情况,减少了不必要的资源消耗和时间浪费。例如,如果多个地方都需要使用数据库连接,传统方式可能会导致数据库连接多次初始化,而 App Startup 会保证数据库连接只在第一次被需要时进行初始化。
  2. 资源优化分配:

    • 由于 App Startup 能够有效地管理初始化过程,它可以根据应用的实际需求合理分配系统资源。在启动过程中,只初始化那些真正必要的组件,避免了不必要的资源占用,使得系统资源能够更有效地用于关键任务的执行,从而提高启动速度。

四、与 Android 系统的集成优化

  1. 利用 Android 系统机制:

    • App Startup 利用了 Android 系统的 ContentProvider 机制来实现组件的初始化。ContentProvider 在应用启动时会被系统自动创建和初始化,这使得 App Startup 能够在合适的时机进行组件初始化,而不会增加额外的启动开销。
    • 同时,ContentProvider 的初始化过程是在系统的管理下进行的,具有一定的稳定性和可靠性。
  2. 高效的初始化触发:

    • 通过与 Android 系统的紧密集成,App Startup 能够在应用启动的早期阶段就开始进行初始化工作,而不是等待应用的其他部分触发初始化。这样可以更早地完成关键组件的初始化,为应用的后续运行做好准备,减少了在应用运行过程中因初始化未完成而导致的等待时间。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • ClimODE——使用神经网络ODE 进行天气预报
  • 日志管理与时钟同步
  • 11 Java 方法引用、异常处理、Java接口之函数式编程(接口知识补充Function<T,R>、BiFunction<T, U, R>和自定义泛型接口)
  • 14个中国各朝代地图图源分享
  • YoloV9改进策略:下采样改进|集成GCViT的Downsampler模块实现性能显著提升|即插即用
  • 燃油车淘汰倒计时开始了?
  • 音视频入门基础:WAV专题(8)——FFmpeg源码中计算WAV音频文件AVStream的time_base的实现
  • echarts处理y轴最大小值根据数据动态处理、分割数和是否从0开始
  • 衡石科技产品手册-指标分析
  • OpenCV绘图函数(14)图像上绘制文字的函数putText()的使用
  • 赞奇科技与华为云共襄828 B2B企业节,激活数字内容“云”创作
  • 理解并优化页面启动时的周期性数据发送代码
  • Java算法之堆排序(Heap Sort)
  • 跨部门协作:搭建共享型客服知识库
  • python网络爬虫(二)——数据的清洗与组织
  • 【comparator, comparable】小总结
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Android交互
  • IDEA 插件开发入门教程
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Java多态
  • Java教程_软件开发基础
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • node学习系列之简单文件上传
  • ReactNativeweexDeviceOne对比
  • ReactNative开发常用的三方模块
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 半理解系列--Promise的进化史
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 前端相关框架总和
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 思考 CSS 架构
  • 微信小程序开发问题汇总
  • 物联网链路协议
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • Android开发者必备:推荐一款助力开发的开源APP
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​zookeeper集群配置与启动
  • ​批处理文件中的errorlevel用法
  • !$boo在php中什么意思,php前戏
  • # Java NIO(一)FileChannel
  • #C++ 智能指针 std::unique_ptr 、std::shared_ptr 和 std::weak_ptr
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • #控制台大学课堂点名问题_课堂随机点名
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (PySpark)RDD实验实战——取最大数出现的次数
  • (第30天)二叉树阶段总结
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程