关于Hilt的运用,现在现已比较普及了,想必咱们现已知道。今日说的是一个如何使用Hilt来做一个发动结构的故事。

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

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

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

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

Hilt 和协程助力启动框架搭建:解决代码混乱和初始化策略问题

你是不是很崩溃,咱们做发动优化的办法一般是,将能并发的并发,能拖延的拖延, 总之要快,要那种让女生瞧不起的快。可是面临这种代码,真的不敢动。

Hilt 和协程助力启动框架搭建:解决代码混乱和初始化策略问题

正文

在 发动优化一文中 我调研过图的发动优化办法

这种发动优化的办法理念是非常好的,今日我要做的操作是,处理乱代码,将初始化分隔做,在这个过程中,我发现能够使用配置引入协程,或有序、或并发、或依靠、或想怎样就怎样,简直爽到不可

使用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()
    }
}

类图如下:

Hilt 和协程助力启动框架搭建:解决代码混乱和初始化策略问题

以下类和接口:

  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 接口,它们之间的联系经过完结联系表明。

完好流程

Hilt 和协程助力启动框架搭建:解决代码混乱和初始化策略问题

  1. User 发动应用程序。
  2. Application 类获取 AppInitializerEntryPoint 接口的实例。
  3. AppInitializerEntryPoint 接口运用 AppInitializersModule 类供给的实例,获取一组应用程序初始化器。
  4. AppInitializerEntryPoint 接口调用每个应用程序初始化器的 init() 办法,按顺序履行初始化使命。
  5. EmojiInitializer 类履行初始化表情符号的使命。
  6. UtilsInitializers 类履行初始化实用工具的使命。

总结

很好的使用Hilt + 协程完结发动结构建立,完美处理代码乱,和初始化战略问题