Android Hilt基类字段注入问题:lateinit属性未初始化异常排查
问题原因
你遇到的kotlin.UninitializedPropertyAccessException核心问题是字段注入时机晚于init块执行:
- DI框架(如Dagger)创建
BaseRepository实例时,会先调用构造函数,紧接着执行init块。 @Inject lateinit var logger的字段注入操作,是在对象完全构造完成后才会执行的步骤。init块中启动的协程是异步执行的,大概率会在logger完成注入前就进入collectLatest回调,此时访问未初始化的lateinit属性就会抛出异常。
解决方案
推荐使用@PostConstruct注解替代init块,该注解标记的方法会在所有依赖注入完成后才被调用,确保logger已完成初始化:
@Singleton open class BaseRepository(private val userService: UserService) { @Inject lateinit var logger: Logger private val scope = CoroutineScope(Dispatchers.Default) private var collectionJob: Job? = null @PostConstruct fun startUserCollection() { collectionJob = scope.launch { userService.flow.collectLatest { logger.setUserId(it?.userId) } } } // 可选:添加销毁方法避免协程内存泄漏 @PreDestroy fun cleanupCollection() { collectionJob?.cancel() } }
额外说明
如果你的DI框架不支持@PostConstruct,可以尝试将logger改为构造注入并借助DI框架的父类依赖自动注入能力:
@Singleton open class BaseRepository @Inject constructor( private val userService: UserService, protected val logger: Logger ) { private val scope = CoroutineScope(Dispatchers.Default) private var collectionJob: Job? = null init { collectionJob = scope.launch { userService.flow.collectLatest { logger.setUserId(it?.userId) } } } } // 子类无需手动传递logger,DI框架会自动注入 @Singleton class HomeRepository @Inject constructor( private val homeService: HomeService, userService: UserService, logger: Logger ) : BaseRepository(userService, logger) { ... }
不过这种方式仍然需要在子类构造函数中声明logger参数,所以优先推荐@PostConstruct方案,完全不需要修改子类代码,符合你的需求。
内容的提问来源于stack exchange,提问作者rysv
相关产品推荐
相关产品推荐

