Jetpack Startup 优雅完成库的初始化和方法接口简化

news2024/11/22 22:05:04

目录

  • 1.Startup组件是什么
  • 2.Startup组件能做啥
    • 2.1 startup组件可以简化用户使用我们提供的库的流程。
    • 2.2 简化库提供给使用者的API接口
  • 3.如何使用Startup组件
    • 3.1 引入依赖
    • 3.2 创建一个初始化的类继承Initializer
    • 3.3 在我们库的AndroidManifest.xml中加入配置
  • 4.使用Startup组件的注意点

1.Startup组件是什么

Startup组件是Google Jetpack推出的,它提供了一种直接高效的方式用来在应用程序启动的时候对多个组件进行初始化,开发者可以依靠它来显示地设置多个组件间的初始化顺序,并优化应用的启动时间。在没有Startup组件之前,很多的三方库为了简化开发者的使用成本,常常会定义一个ContentProvider获取Context的对象,然后自动完成库的初始化,也就是我们之前使用库的时候,总是需要在Application中调用下某某库的:XXXLib.init(Context)方法,主要是将我们的Context传递给三方库。由于ContentProvider会在Application的onCreate()之前调用,所以可以通过定义ContentProvider的方式提前获取到Context。但是这样做会有问题的,因为如果每个三方库都定义一个自己的ContentProvider,并且在拿Context的时候都做了耗时操作,这样就会导致应用的启动变慢和长时间黑屏的问题。因此,Google就推出了Startup组件,Startup组件允许库的开发者和App的开发者共享一个ContentProvider,用于完成各自的初始化逻辑,并且支持设置组件之间的初始化顺序。这样应用就可以选择先初始化需要马上使用到的库,其他的不需要马上使用的库后面再初始化。从而达到缩短应用的启动时间。

2.Startup组件能做啥

2.1 startup组件可以简化用户使用我们提供的库的流程。

比如我们非常熟悉的内存泄漏检测工具LeakCarry,在没有使用Startup组件之前,使用它需要在Application中初始化一下,如下所示:

在这里插入图片描述也就是说用户不仅需要引入依赖,还需要做初始化工作。但是引入了startup组件后,使用LeakCanary就可以只引入依赖了。LeakCanary库会通过startup组件提供的API拿到想要的Context,然后进行内存泄漏的检测工作。下面是LeakCanary库使用startup组件的截图:
首先是Manifest中

在这里插入图片描述初始化类:
在这里插入图片描述然后我们就可以看到在LeakCanary库中就能拿到了Context并进行初始化了。所以我们使用的时候,只需要引入依赖:

dependencies {
  // debugImplementation because LeakCanary should only run in debug builds.
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
}

就可以使用LeakCanary库检测内存泄漏了。

2.2 简化库提供给使用者的API接口

现在的VR眼镜基本上都是基于Android系统的,而3D场景的渲染都依赖于Unity和OpenGL,Unity和OpenGL渲染时的数据有一部分是需要Android系统提供的,所以就需要Android开发接口提供给Unity或者是OpenGL调用。但是很多的时候接口都需要使用单例的方式提供并且需要传递Context,如下所示:

在这里插入图片描述这样调用者在调用的时候就需要使用LoadAllAPIEngine.getInstance(context).getInfo()的方式去使用我们提供的服务,而且还需要调用下LoadAllAPIEngine.getInstance(context).init()方法让我们提供接口的库做一些初始化的动作。在开发的过程中发现使用接口的同事会经常多次调用init()方法,或者是忘记调用release()方法,导致出现一些未知的问题。而且如果是OpenGL调用我们的接口时,往往需要反射获取Android的Context,然后再每次调用接口时传递给提供服务的sdk库。这些都增加了SDK使用者的负担,同时也让我们查问题时显得很吃力。

而利用Startup组件可以可以解决这个问题,使用了startup组件后,使用者只要引入我们的库依赖,就可以使用我们的提供的接口方法获取到想要的信息了,使用startup组件后,调用接口就可以变成。 LoadAllAPIEngine.getInstance().getInfo()了,并且不用调用LoadAllAPIEngine.getInstance(context).init()方法,直接使用接口即可。

3.如何使用Startup组件

3.1 引入依赖

implementation("androidx.startup:startup-runtime:1.1.1")

3.2 创建一个初始化的类继承Initializer

然后重写create()方法和dependencies()方法。然后在create()方法中就可以拿到引用我们库的APP的Context了。

class StartupInitializer : Initializer<StartupInitializer>{
    override fun create(context: Context): StartupInitializer = apply {
        val application = context.applicationContext as Application
        application.registerActivityLifecycleCallbacks(object 
        :ActivityLifecycleCallbacks{
            override fun onActivityCreated(activity: Activity, 
            savedInstanceState: Bundle?) {
                FMSdk.getInstance().init(activity)
                Log.d(TAG,"onActivityCreated")
            }

            override fun onActivityStarted(activity: Activity) {

            }

            override fun onActivityResumed(activity: Activity) {
                FMSdk.getInstance().resume()
                Log.d(TAG,"onActivityResumed")

            }

            override fun onActivityPaused(activity: Activity) {

            }

            override fun onActivityStopped(activity: Activity) {
                FMSdk.getInstance().pause()
                Log.d(TAG,"onActivityStopped")
            }

            override fun onActivitySaveInstanceState(activity: Activity, 
            outState: Bundle) {

            }

            override fun onActivityDestroyed(activity: Activity) {
                FMSdk.getInstance().release()
                Log.d(TAG,"onActivityDestroyed")
            }

        })
    }

    //获取在初始化自身之前需要先初始化的其他Initializer 列表 ,
    // 这里有助于我们管理库的依赖顺序,比如我们的库依赖其他的库A,并且需要在
    // A之后进行初始化,就可以在这里配置
    //如果不需要依赖于其它组件,则可以返回一个空列表
    override fun dependencies()  = emptyList<Class<out Initializer<*>>>()
}

3.3 在我们库的AndroidManifest.xml中加入配置

定义好初始化的类后,我们需要在我们的库项目中声明一个provider,配置authorities为引用我们库的app的包名+“.androidx-startup”,然后定义一个<meta-data …/>节点,将我们定义的初始化类引用配置上去,这里我定义的类引用为:com.nolovr.core.fmsdk.engine.StartupInitializer。具体配置参考下面代码。

<application>
    <provider
        android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <meta-data
            android:name="com.nolovr.core.fmsdk.engine.StartupInitializer"
            android:value="androidx.startup"
            />
    </provider>    
</application>

上面的步骤配置完后,开发者接入我们的库时就可以直接引入依赖,然后直接调用我们的库中的对应方法,不用再去Application下去做啥初始化操作啦

4.使用Startup组件的注意点

(1)使用Startup我们需要注意不能在StartupInitializer 的create()方法中做耗时操作,因为create方法是在主线程被调用的,如果做耗时操作会导致初始化时间变长,导致应用出现启动慢,黑白屏的问题。
(2)在引用库的主项目中不能使用tools:node=“remove” 的语句要求在合并 AndroidManifest 文件时移除自身否则自动初始化的功能就无法使用了。例如不能在主项目中做如下配置:

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data
        android:name="com.nolovr.core.fmsdk.engine.StartupInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>

或者是:

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

因为这样会导致我们的startup组件不生效,当然,如果是想自己手动初始化库的情况下除外。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows mysql5.7 执行查询/开启/测试binlog---简易记录

前言&#xff1a;基于虚拟机mysql版本为5.7&#xff0c;增量备份测试那就要用到binlog… 简述&#xff1a;二进制日志&#xff08;binnary log&#xff09;以事件形式记录了对MySQL数据库执行更改的所有操作。 binlog是记录所有数据库表结构变更&#xff08;例如CREATE、ALTER…

C++相关闲碎记录(9)

1、非修改型算法 for_each()对每个元素执行某种操作count()返回元素个数count_if()返回满足某一条件的元素的个数min_element()返回最小值元素max_element()返回最大值元素minmax_element()返回最小值和最大值元素find()查找某个数值find_if()查找满足条件的元素find_if_not()…

03 Temporal 详细介绍

前言 在后端开发中&#xff0c;大家是否有遇到如下类型的开发场景 需要处理较多的异步事件需要的外部服务可靠性较低需要记录保存某个对象的复杂状态 在以往的开发过程中&#xff0c;可能更多的直接使用数据库、定时任务、消息队列等作为基础&#xff0c;来解决上面的问题。然…

【概率方法】MCMC 之 Gibbs 采样

上一篇文章讲到&#xff0c;MCMC 中的 HM 算法&#xff0c;它可以解决拒绝采样效率低的问题&#xff0c;但是实际上&#xff0c;当维度高的时候 HM 算法还是在同时处理多个维度&#xff0c;以两个变量 x [ x , y ] \mathbf{x} [x,y] x[x,y] 来说&#xff0c;也就是同时从联合…

Nyquist Theorem(取样定理)

取样定理&#xff0c;又称为奈奎斯特定理&#xff08;Nyquist Theorem&#xff09;&#xff0c;是信号处理领域中一项至关重要的基本原理。它规定了对于连续时间信号&#xff0c;为了能够完全准确地还原出原始信号&#xff0c;即使是在离散时间下进行采样和再构建&#xff0c;都…

算法基础之树的重心

树的重心 无向图: 边没有方向 有向图:边有方向 只能单向询问 无向图建立双向的边 要求输出每种情况连通块个数最大值的最小值**(最小的最大值)** #include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace s…

2023-12-13 VsCode + CMake + Qt环境搭建

点击 <C 语言编程核心突破> 快速C语言入门 VsCode CMake Qt环境搭建 前言一、前期准备二、具体设置总结 前言 要解决问题: 最近研究 Qt, 使用 qtcreator, 发现在搭建 UI 界面时候很方便, 但到编码和调试就比较有问题了. 想到的思路: 用 VSCode 进行编码及调试. 其它…

003 FeedForward前馈层

一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17torch 1.13.1cu117torchvision 0.14.1cu117 二、前馈层原理 Transformer模型中的前馈层&#xff08;Feed Forward Layer&#xff09;是其关键组件之一&#xff0c;对于模型的性能起着重要作用。下面将用900字对…

postman接口测试系列: 时间戳和加密

在使用postman进行接口测试的时候&#xff0c;对于有些接口字段需要时间戳加密&#xff0c;这个时候我们就遇到2个问题&#xff0c;其一是接口中的时间戳如何得到&#xff1f;其二就是对于现在常用的md5加密操作如何在postman中使用代码实现呢&#xff1f; 下面我们以一个具体的…

【EXCEL】数据透视实例

相关链接&#xff1a;Excel数据透视表全攻略 数据样例&#xff1a; 透视结果&#xff1a;

分析某款go端口扫描器之三

一、概述 前两篇主要分析些工具集&#xff0c;已经针对web服务的指纹和端口指纹信息进行识别&#xff0c;并没有真正开始扫描。本篇主要分析如何进行IP存活探测以及tcp扫描实现。 项目来源&#xff1a;https://github.com/XinRoom/go-portScan/blob/main/util/file.go 二、/…

云架构俭约之道七法则(The Frugal Architect)

文章目录 一、前言关于 Law 与 Rule 的区别 二、云架构俭约之道七法则Design&#xff08;设计方面&#xff09;Law 1&#xff1a;把成本作为非功能性需求Law 2&#xff1a;可持续性系统需要将成本与业务相匹配Law 3&#xff1a;架构设计是一系列权衡的取舍 Measure&#xff08;…

Unity | 渡鸦避难所-2 | 搭建场景并添加碰撞器

1 规范项目结构 上期中在导入一系列的商店资源包后&#xff0c;Assets 目录已经变的混乱不堪 开发过程中&#xff0c;随着资源不断更新&#xff0c;遵循一定的项目结构和设计规范是非常必要的。这可以增加项目的可读性、维护性、扩展性以及提高团队协作效率 这里先做下简单的…

vivado约束方法2

排序约束条件 因为XDC约束是按顺序应用的&#xff0c;并且是基于明确的优先级排列的规则&#xff0c;您必须仔细检查约束的顺序。 Vivado IDE为您的设计提供了全面的可视性。要逐步验证约束&#xff0c;请执行以下操作&#xff1a; 1.运行相应的报告命令。 2.查看Tcl控制台…

微信小程序自定义提示框组件并使用插槽 tooltip

创建tooltip组件引用 创建一个自定义组件&#xff0c;例如命名为 tooltip tooltip.wxml&#xff1a;用于定义组件的结构&#xff1b; <!--components/tooltip/tooltip.wxml--> <view class"tooltip-wrapper" hidden"{{hidden}}" style"lef…

spingboot项目实战之若依框架创建新模块

前言 目前的脚手架系统很多&#xff0c;比较早接触诺依框架&#xff0c;以若依框架为参考如何创建新模块 步骤 1. 下载诺依框架&#xff0c;依照参考说明一步步&#xff0c;能做到系统运行起来。 2. 准备好mysql文件&#xff0c;创建新数据库表 3. 数据库管理工具navicat…

如何退回chrome旧版ui界面?关闭Chrome浏览器新 UI 界面

之前启用新UI的方式 Chrome 已经很久没有进行过大的样式修改&#xff0c;但近期在稳定分支中添加了新的 flags 实验性标志&#xff0c;带来了全新的设计与外观&#xff0c;启用方式如下&#xff1a; 在 Chrome 浏览器的搜索栏中输入并访问 chrome://flags 搜索“refresh 2023…

Leetcode 46 全排列

题意理解&#xff1a; 首先明确全排列是什么&#xff1f; 使用集合里所有的元素&#xff0c;使用不同的顺序进行排列&#xff0c;所有的排列集合即为全排列。 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 这里的元素不会…

《YOLOv8改进系列》专栏目录介绍

YOLOv8改进系列 &#x1f680; 专栏目录介绍 本专栏内容是紧跟最新、最前沿的改进方法&#xff0c;不仅适用检测任务&#xff0c;分类任务&#xff0c;分割任务&#xff0c;关键点任务同样适用。文章适用于多种场景&#xff0c;包括但不限于小目标、工业缺陷、轻量化等领域。 …

猫粮哪个牌子质量好性价比高?口碑比较好的主食冻干猫粮牌子推荐

猫咪生骨肉主食冻干猫粮喂养方式是越来越火了&#xff0c;作为一个离职的十年经验宠物护理师&#xff0c;对宠物健康营养方面的知识一直在研究&#xff0c;不光是为了我自己养的猫咪身体健康&#xff0c;也要为客户的猫咪健康负责&#xff01;现在很多养猫人士对主食冻干猫粮喂…