Jetpack—架构组件—App Startup

简介: Jetpack—架构组件—App Startup

App Startup


介绍作用

image.png

这是官网的截图,大意就是 App Startup 是一种用来在 app 启动时候规范初始化数据的 library。同时使用 App Startup 可以解决我们平时滥用 ContentProvider 导致的启动变慢问题。

还有一点,App Startup 可以用于 app 开发,也可以用来进行 sdk 开发


App Startup 的优势

  1. 平时使用 ContentProvider 自动获取 ApplicationContext 的方式管理混乱,并且多个 ContentProvider 初始化的方式也无法保证初始化的顺序
  2. 统一管理的方式可以明显提升 app 初始化速度,注:仅限于用较多 ContentProvider 来初始化应用的 app,反之不是不能用,只是没有优化效果


依赖

dependencies {
    implementation("androidx.startup:startup-runtime:1.0.0")
}
复制代码


使用 AppStartup 初始化全局单例对象(main 分支)

  1. Car 对象
class Car(private val name: String) {
    companion object {
        var instance: Car? = null
        fun getInstance(name: String): Car {
            if (instance == null) {
                instance = Car(name)
            }
            return instance!!
        }
    }
    override fun toString(): String {
        return "$name  ${Random.nextInt(100)}"
    }
}
复制代码


  1. 首先需要实现一个 Initializer
class AndroidInitializer : Initializer<Car> {
    override fun create(context: Context): Car {
        return Car.getInstance("出租车")
    }
    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf()
    }
}
复制代码


  1. 在代码中注册 AndroidInitializer
<provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
          >
            <meta-data
                android:name="com.ananananzhuo.appstartupdemo.AndroidInitializer"
                android:value="androidx.startup" />
        </provider>
复制代码


  1. 分析

本例中 Car 对象,Car 对象内部维护了一个全局单例方法 getInstance。

前面说了,AppStartup 是用来维护全局单例的,那么实际上这个单例的初始化就是通过我们定义的 AndroidInitializer 对象 create 方法来初始化的。


  1. 我们会在 MainActivity 中调用 Car 的 toString 方法,代码如下
logEE(Car.getInstance("小汽车:").toString())
        logEE(Car.getInstance("小汽车:").toString())
        logEE(Car.getInstance("小汽车:").toString())
复制代码

我们调用了,三次 toString 方法

代码输出如下:

image.png

我们 MainActivity 中代码 getInstance 传入的参数是 "小汽车",但是打印的却是 "出租车"。查看 AndroidInitializer 中的代码发现,我们在 AndroidInitializer 中的 create 方法中创建对象的参数是 "出租车"。

由此可以证明,我们的全局 Car 单例在 AndroidInitializer 中就已经初始化完成了。


手动初始化组件

上一节中我们使用在 Manifest 中注册组件的方式实现 Car 对象的自动初始化。

但是,实际上我们是可以不在 Manifest 中注册的方式实现初始化的,手动初始化的方式如下:

AppInitializer.getInstance(this)
            .initializeComponent(AndroidInitializer::class.java)
复制代码

这种方式的弊端是一次只能初始化一个组件


实现相互依赖的多实例的初始化(分支:multimodule)

通过上一节的学习,你可能会有这样的疑问:AppStartup 啥用没有吧,我直接在 Application 中一行代码初始化不香吗,非要用你这种方式???

那么现在我就要用 AppStartup 实现多实例的初始化,让你进一步了解 AppStartup 的应用


我们这一节的逻辑先描述一下:

本例中我们需要创建两个对象,Person 和 Noodle,两者都是全局单例的。

Person 持有 Noodle 对象的引用,

Person 中有一个 eat 方法,本例中我们的 eat 会输出一行 "某某人" 吃 "面条" 的日志

废话不多说,上代码:

不要嫌代码长,都是一看就懂的逻辑

  1. Person 和 Noodle
class Person(val name:String) {
    private var noodle: Noodle? = null
    companion object {
        private var instance: Person? = null
        fun getInstance(name:String): Person {
            if (instance == null) {
                instance = Person(name)
            }
            return instance!!
        }
    }
    fun addNoodle(paramsnoodle: Noodle) {
        noodle = paramsnoodle
    }
    fun eat() {
        logEE("${name} 吃 ${noodle?.name}")
    }
}
复制代码


class Noodle {
    val name = "面条"
    companion object {
        private var instance: Noodle? = null
        fun getInstance(): Noodle {
            if (instance == null) {
                instance = Noodle()
            }
            return instance!!
        }
    }
}
复制代码


  1. PersonInitializer、NoodleInitializer
class PersonInitializer : Initializer<Person> {
    override fun create(context: Context): Person {
        return Person.getInstance("李白").apply {
            addNoodle(Noodle.getInstance())
        }
    }
    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf(NoodleInitializer::class.java)
    }
}
复制代码


class NoodleInitializer:Initializer<Noodle> {
    override fun create(context: Context): Noodle {
        return Noodle.getInstance()
    }
    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
        return mutableListOf()
    }
}
复制代码

这两个组件中 PersonInitializer 的 create 方法中创建了 Person 的实例,并向里面添加 Noodle 的实例。


划重点:

PersonInitializer 的 dependencies 方法中返回了 mutableListOf(NoodleInitializer::class.java)。这句代码的意思是在 PersonInitializer 中的 Person 初始化之前会先初始化 NoodleInitializer 中的 Noodle 实例,然后当 PersonInitializer 中 addNoodle 的时候 Noodle 全局单例已经创建好了。

  1. 调用吃面条方法
Person.getInstance("杜甫").eat()
复制代码
  1. 打印日志输出

image.png

日志输出符合我们的预期

多实例的注册组件方式如下,我们将 PersonInitializer、NoodleInitializer 都被注册到 meta-data 中了。

实际上,NoodleInitializer 的组件是完全可以不注册的,因为在 PersonInitializer 的 dependencies 中已经声明了 NoodleInitializer 组件。

<provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false">
            <meta-data
                android:name="com.ananananzhuo.appstartupdemo.PersonInitializer"
                android:value="androidx.startup" />
            <meta-data
                android:name="com.ananananzhuo.appstartupdemo.NoodleInitializer"
                android:value="androidx.startup" />
        </provider>
复制代码


使用 AppStartup 进行 sdk 开发(分支:sdk_develop)

本例介绍 sdk 开发中 AppStartup 的使用,实际上与应用开发是一样的,但是感觉还是有必要说一下。

在本例中我们新建了一个 library 的 module,在 library 里面编写了我们的 AppStartup 的代码逻辑,然后将 Library 打包成 arr,集成到 app 模块中,在 app 的 Manifest 中注册组件,并调用组件的相关方法。

  1. aar 集成

image.png

  1. library 中的代码
class LibraryInitializer:Initializer<Student> {
    override fun create(context: Context): Student {
        return Student.getInstance()
    }
    override fun dependencies(): MutableList<Class<out Initializer<*>>> {
       return mutableListOf()
    }
}
复制代码


class Student(val name: String) {
    companion object {
        private val student = Student("安安安安卓")
        fun getInstance(): Student {
            return student
        }
    }
    fun study() {
        Log.e("tag", "${name}  好好学习")
    }
}
复制代码


  1. Manifest 中注册组件
<provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="com.ananananzhuo.appstartupdemo.androidx-startup"
            android:exported="false"
          >
            <meta-data
                android:name="com.ananananzhuo.library.LibraryInitializer"
                android:value="androidx.startup" />
        </provider>
复制代码


  1. 日志打印

image.png


  1. 结论

通过这种方式,第三方 sdk 只需要定义自己的 AppStartup 组件就可以,我们在注册组件的时候在 manifest 中添加第三方组件的信息就可以完成第三方组件的初始化了。

这极大的避免了某些自以为是的 sdk,打着方便我们集成的名义搞 ContentProvider 初始化恶心我们

以后如果你合作的第三方 sdk 提供方再出现 ContentProvider 的初始化方式恶心你,那么拿出我的文章好好教他做人。



相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
3月前
|
JSON 自然语言处理 数据格式
使用Tabs选项卡组件快速搭建鸿蒙APP框架
ArkUI提供了很多布局组件,其中Tabs选项卡组件可以用于快速搭建鸿蒙APP框架,本文通过案例研究Tabs构建鸿蒙原生应用框架的方法和步骤。
401 5
使用Tabs选项卡组件快速搭建鸿蒙APP框架
|
5月前
|
小程序 安全 JavaScript
构建即时通讯APP内的小程序生态体系:从架构设计到技术实现-优雅草卓伊凡
构建即时通讯APP内的小程序生态体系:从架构设计到技术实现-优雅草卓伊凡
347 1
构建即时通讯APP内的小程序生态体系:从架构设计到技术实现-优雅草卓伊凡
|
10月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
679 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
11月前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
393 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
6月前
《仿盒马》app开发技术分享-- 积分页组件新增(64)
上一节我们创建了积分页,给页面添加了标题栏和积分展示的组件。这一节我们继续丰富积分页的内容,添加引导栏,积分明细展示等区域
139 0
|
8月前
|
人工智能 小程序 API
【一步步开发AI运动APP】四、使用相机组件抽帧
本文介绍了如何使用`ai-camera`组件开发AI运动APP,助力开发者深耕AI运动领域。`ai-camera`是专为AI运动场景设计的相机组件,支持多平台,提供更强的抽帧处理能力和API。文章详细讲解了获取相机上下文、执行抽帧操作以及将帧保存到相册的功能实现,并附有代码示例。无论是AI运动APP还是其他场景,该组件都能满足预览、拍照、抽帧等需求。下篇将聚焦人体识别检测,敬请期待!
|
11月前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
380 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
882 4
|
缓存 小程序 索引
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
926 1
|
存储 API 数据库
uniapp APP自动更新组件
uniapp APP自动更新组件
536 1

热门文章

最新文章