在Hilt中如何在Kotlin类init代码块内调用已注入对象的方法
你的崩溃原因确实是Hilt注入时序问题:字段注入的执行时机在构造函数、init代码块全部执行完毕之后,因此init块运行时@Inject标记的lateinit字段还未完成赋值,就会抛出未初始化异常。
以下是优先级从高到低的优雅实现方案:
方案1:优先改用构造函数注入(最推荐)
把依赖直接通过构造函数注入,这样构造执行时依赖已经完成赋值,init块可以直接正常调用,不需要依赖字段注入,同时也避免了lateinit的空安全风险,完全符合Dagger/Hilt的设计规范。
修改后的示例代码:
// 仅需修改Test2的注入方式即可 class Test2 @Inject constructor( // 将ITest1改为构造参数注入 private val test1: ITest1 ): ITest2 { override fun doSomethingElse() { println("Something else ") } // 此时init块可以正常访问test1 init { test1.doSomething() } }
方案2:使用@PostConstruct注解执行初始化
如果因为业务逻辑限制确实不能改用构造函数注入,可以用@PostConstruct注解标记初始化方法,Hilt会在所有字段注入完成后自动调用该方法,无需在Module中手动处理。
示例代码:
import javax.annotation.PostConstruct class Test2 @Inject constructor(): ITest2 { @Inject lateinit var test1: ITest1 override fun doSomethingElse() { println("Something else ") } // 去掉原init块,初始化逻辑移到被@PostConstruct标记的方法中 @PostConstruct fun initAfterInject() { test1.doSomething() } }
注意该方法必须是无参数的,且每个类只能有一个被@PostConstruct标记的方法。
方案3:自定义初始化方法(你当前的临时方案)
如果前两种方案都不满足需求,才推荐用手动调用初始化的方案,适合需要传入自定义初始化参数的特殊场景。
内容的提问来源于stack exchange,提问作者Ivan Škugor
相关产品推荐
相关产品推荐

