Dagger Hilt向Fragment字段注入时偶现lateinit属性未初始化错误如何解决
问题原因分析
- Hilt对
@AndroidEntryPoint注解的Fragment的字段注入逻辑默认在onAttach()生命周期方法中执行,你遇到的偶现未初始化问题属于Hilt低版本的已知时序bug,在Fragment转场、导航快速切换、ViewPager预加载等场景下,onViewCreated()的执行时机可能早于注入逻辑完成,从而触发UninitializedPropertyAccessException - 也有可能是你重写了Fragment的
onAttach()方法但未调用super.onAttach(),导致注入逻辑没有被执行,系统版本差异会放大这个问题导致偶现。
修复方案
方案1:改用构造注入(推荐)
你对Fragment无法使用构造注入的认知是错误的,从AndroidX Fragment 1.2.0版本开始就支持构造参数注入,配合Hilt可以直接避免lateinit未初始化的问题,修改代码如下:
@AndroidEntryPoint class AccountFragment @Inject constructor( val dialogHandler: DialogHandler ) : Fragment(R.layout.fragment_account) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val currentDialogKey = dialogHandler.currentDialogKey // 不会再出现未初始化异常 //.... //.... } }
方案2:升级Hilt版本
如果你坚持使用字段注入,将Hilt版本升级到2.34及以上即可,官方在该版本修复了Fragment生命周期注入的竞态问题。
方案3:临时兼容处理
如果暂时无法升级版本或修改注入方式,可以通过延迟执行访问逻辑规避时序问题:
@AndroidEntryPoint class AccountFragment : Fragment(R.layout.fragment_account) { @Inject lateinit var dialogHandler: DialogHandler override fun onViewCreated(view: View, savedInstanceState: Bundle?) { // 将逻辑post到View的消息队列,确保注入完成后再执行 view.post { val currentDialogKey = dialogHandler.currentDialogKey //.... //.... } } }
也可以配合lateinit的初始化判断做双重保障:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { if (::dialogHandler.isInitialized) { val currentDialogKey = dialogHandler.currentDialogKey // 直接执行业务逻辑 } else { view.post { val currentDialogKey = dialogHandler.currentDialogKey // 延迟执行逻辑 } } }
内容的提问来源于stack exchange,提问作者Arpit Shukla
相关产品推荐
相关产品推荐

