Hilt 和协程助力启动框架:解决启动代码混乱

作者:麦客奥德彪

链接:

https://juejin.cn/post/7219229724958801976

本文由作者授权发布。

关于Hilt的使用,目前已经比较普及了,想必大家已经知道。今天说的是一个如何利用Hilt来做一个启动框架的故事。

是否经历过大型项目的启动优化,一遍过去无任何效果,第二遍过去好几处报错,第三遍过去启动不了,第四遍过去回滚了代码 这都是为什么呢?

不要怀疑,不要询问,不是你技术菜,也不是逻辑有问题(当然没问题,有问题就不叫优化了,叫改bug),而是启动代码写的乱。

在我们软件行业中,或者说每个人的人生中,乱 这一个字,让多少人悲痛欲绝,让多少人从成功走向了落寞,咳咳,让多少软件行业增本、让多少软件行业无利。

当你打开Application 他的代码量是这样的:

8e0abcb2777410f7875eeb8be8dcede3.jpeg

你是不是很崩溃,我们做启动优化的手法一般是,将能并发的并发,能延后的延后, 总之要快,要那种让女生看不起的快。但是面对这种代码,真的不敢动。

https://juejin.cn/post/7119368593644470285

正文

在 启动优化一文中 我调研过图的启动优化方式。

https://juejin.cn/post/7119368593644470285

这种启动优化的方式理念是非常好的,今天我要做的操作是,解决乱代码,将初始化分开做,在这个过程中,我发现可以利用配置引入协程,或有序、或并发、或依赖、或想怎样就怎样,简直爽到不行。

利用Hilt 搭建启动框架
  • 首先,使用接口约束初始化框架

 
 
// 后续都需要依赖此框架
interface AppInitializer {
    fun init()
}
  • 其次,将实现了此接口的初始化器,分开并连起来

 
 
class AppInitializers @Inject constructor(
    private val application: Application,
) {

    private val initializers: Set<AppInitializer> by lazy {
        EntryPointAccessors.fromApplication(application, AppInitializerEntryPoint::class.java)
            .getAppInitializers()
    }

    fun init() {
        for (initializer in initializers) {
            initializer.init()
        }
    }
}

提供一个初始化入口,此代码将在APPlication 中调用,我们使用Hilt注解完成Set<AppInitialize> 的收集,并且在Application中调用init时 启动初始化,注意 这个地方(init)可以将Set 变为Map,指定策略,实现“或有序、或并发、或依赖、或想怎样就怎样,简直爽到不行”。

  • 最后,使用

Application 中调用

 
 
initializers.init()
Hilt 部分代码
 
 
@EntryPoint
@InstallIn(SingletonComponent::class)
interface AppInitializerEntryPoint {
    fun getAppInitializers(): Set<AppInitializer>
}

将所初始化器,分别注册到启动器中。

 
 
@Module
@InstallIn(SingletonComponent::class)
object AppInitializersModule {
    @Provides
    fun provideAppInitializers(application: Application): Set<AppInitializer> {
        return setOf(
            EmojiInitializer(application),
            UtilsInitializers(application),
        )
    }
}

这个代码比较简单,这就完事了,将乱代码直接分离开了。

制定策略

乱代码是分开了,但是其实用性只在编码层面,想要达到“或有序、或并发、或依赖、或想怎样就怎样,简直爽到不行”这种境界,还需要添加策略。

修改注册器

 
 
fun getStrategyAppInitializers(): Map<AppInitializer.AppInitializerStrategy, List<AppInitializers>>

我们提供一个策略类:

 
 
enum class AppInitializerStrategy {
    SERIAL,
    PARALLEL,
}

添加到总注册器:

 
 
@Provides
fun provideStrategyAppInitializers(application: Application): Map<AppInitializer.AppInitializerStrategy, List<AppInitializer>> {
    return mapOf(
        AppInitializer.AppInitializerStrategy.SERIAL to arrayListOf(EmojiInitializer(application)),
        AppInitializer.AppInitializerStrategy.PARALLEL to arrayListOf(UtilsInitializers(application)),
    )
}

然后在总的启动器中根据不同的策略配合协程一起使用:

 
 
strategyInitializers[AppInitializer.AppInitializerStrategy.SERIAL]?.forEach {
    it.init()
}

strategyInitializers[AppInitializer.AppInitializerStrategy.PARALLEL]?.forEach {
    MainScope().launch(Dispatchers.IO) {
        it.init()
    }
}

类图

类图如下:

7c9225cba908579dd6e29e8c05aaccf1.jpeg

以下类和接口:

  1. Application:Android 应用程序类。

  2. AppInitializer 接口:定义了一个 init() 方法,该方法将在应用程序启动时调用,用于执行一些初始化任务。

  3. EmojiInitializer 类:实现了 AppInitializer 接口,用于初始化表情符号相关的内容。

  4. UtilsInitializers 类:实现了 AppInitializer 接口,用于初始化一些实用工具。

  5. AppInitializerEntryPoint 接口:定义了获取应用程序初始化器的方法,以及获取不同策略的应用程序初始化器列表的方法。

  6. AppInitializersModule 类:使用 Dagger2 提供 AppInitializerEntryPoint 接口的实例。

  7. AppInitializerStrategy 枚举类:定义了应用程序初始化器的两种不同的策略:串行和并行。

以下关系:

  1. Application 类与 AppInitializerEntryPoint 接口之间的关系:Application 类使用 AppInitializerEntryPoint 接口来获取应用程序初始化器。

  2. AppInitializerEntryPoint 接口与 AppInitializer 接口之间的关系:AppInitializerEntryPoint 接口使用 AppInitializer 接口来表示应用程序初始化器。

  3. AppInitializersModule 类与 AppInitializerEntryPoint 接口之间的关系:AppInitializersModule 类提供了一个 AppInitializerEntryPoint 接口的实例。

  4. AppInitializersModule 类与 AppInitializer 接口之间的关系:AppInitializersModule 类提供了一组 AppInitializer 接口的实例。

  5. EmojiInitializer 类和 UtilsInitializers 类都实现了 AppInitializer 接口,它们之间的关系通过实现关系表示。

完整流程

3c782b0442cd1849223630d821b01738.jpeg

  1. User 启动应用程序。

  2. Application 类获取 AppInitializerEntryPoint 接口的实例。

  3. AppInitializerEntryPoint 接口使用 AppInitializersModule 类提供的实例,获取一组应用程序初始化器。

  4. AppInitializerEntryPoint 接口调用每个应用程序初始化器的 init() 方法,按顺序执行初始化任务。

  5. EmojiInitializer 类执行初始化表情符号的任务。

  6. UtilsInitializers 类执行初始化实用工具的任务。

总结

很好的利用Hilt + 协程完成启动框架搭建,完美解决代码乱,和初始化策略问题。

源码: 

https://github.com/kongxiaoan/IM-Middleware

关注我获取更多知识或者投稿

cb05d6e8e8bfb539269873f1c8b1857c.jpeg

851d0b28e63d6cefcd700880d47caec0.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值