Dagger Hilt报UninitializedPropertyAccessException: lateinit属性homeView未初始化如何解决
报错原因
HomeFeedViewModel中的lateinit homeView未添加@Inject注解,Hilt无法识别需要为该字段注入实例,导致属性始终未初始化,访问时直接抛出异常。- 你将
HomeView的绑定安装在了SingletonComponent(全局单例组件)中,但HomeView的实现类是Frag_home(Fragment),Fragment生命周期远短于单例组件的生命周期,Hilt无法在单例域中获取到正确的Fragment实例完成注入,即使加了注解也会注入失败甚至引发内存泄漏。 HomeFeedViewModel未添加@HiltViewModel注解,构造函数也没有添加@Inject注解,Hilt本身就无法正常实例化ViewModel并完成成员注入。
修复方案
方案1(适配现有MVP风格写法)
不建议通过Hilt注入View层接口,改为手动绑定更安全:
- 给ViewModel添加Hilt注解,调整homeView属性定义:
@HiltViewModel class HomeFeedViewModel @Inject constructor( val applicationContext: Context, val repo: repository ) : ViewModel() { var homeView: HomeView? = null // 改为可空类型,销毁时置空避免内存泄漏 }
- 在
Frag_home中手动绑定、解绑View接口:
@AndroidEntryPoint class Frag_home : Fragment(), HomeView { private val viewModel: HomeFeedViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.homeView = this } override fun onDestroyView() { viewModel.homeView = null // 销毁时务必置空 super.onDestroyView() } // 其余HomeView接口实现逻辑保持不变 }
- 删除
InterfaceModule中getHomeView的绑定逻辑,避免单例持有Fragment实例引发泄漏。
方案2(符合MVVM最佳实践)
完全淘汰View接口回调,改为在ViewModel中暴露Flow/LiveData,Fragment观察数据实现回调,无需手动绑定View:
@HiltViewModel class HomeFeedViewModel @Inject constructor( val applicationContext: Context, val repo: repository ) : ViewModel() { private val _feedState = MutableSharedFlow<FeedState>() val feedState = _feedState.asSharedFlow() // 加载成功后发送对应事件 suspend fun loadFeedSuccess(showPostBean: ArrayList<Data_model>, lastPage: String, currentPage: String) { _feedState.emit(FeedState.SuccessLoadFeed(showPostBean, lastPage, currentPage)) } // 其余状态同理封装 sealed class FeedState { data class SuccessLoadFeed(val showPostBean: ArrayList<Data_model>, val lastPage: String, val currentPage: String) : FeedState() data class SuccessNoContent(val msg: String) : FeedState() data class SuccessLocation(val userBean: Data_model) : FeedState() data class SuccessLikePost(val likePostBean: Data_model) : FeedState() } }
Fragment中观察事件即可:
lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.feedState.collect { state -> when(state) { is FeedState.SuccessLoadFeed -> OnSuccessLoadFeed(state.showPostBean, state.lastPage, state.currentPage) is FeedState.SuccessNoContent -> onSuccessNoContent(state.msg) is FeedState.SuccessLocation -> onSuccessLocation(state.userBean) is FeedState.SuccessLikePost -> onSuccessLikePost(state.likePostBean) } } } }
内容的提问来源于stack exchange,提问作者hardik koladiya
相关产品推荐
相关产品推荐

