使用by navGraphViewModels()配合Hilt初始化接口ViewModel报ClassCastException
问题解决方案
错误根因
by navGraphViewModels() 委托的泛型参数默认约束为必须继承ViewModel类,你直接用自定义接口ExampleViewModelController作为变量接收类型时,编译器会将委托的泛型推断为该接口类型,但接口不属于ViewModel子类,导致ViewModelProvider返回实例时内部类型转换失败,抛出ClassCastException。
解决方法
你可以通过「先获取具体ViewModel实现类实例,再对外暴露接口类型引用」的方式实现需求,既保留了导航图作用域共享ViewModel的能力,也满足你隐藏ViewModel内部实现、仅暴露指定接口方法的设计要求,修改后的代码如下:
Fragment修改后代码
@AndroidEntryPoint class ExampleFragment : Fragment() { // 先通过委托获取具体的ViewModel实现类实例,不对外暴露 private val implViewModel: ExampleViewModel by navGraphViewModels(R.id.nav_graph_example) // 对外仅暴露接口能力,外部使用时只能调用接口定义的方法 private val viewModel: ExampleViewModelController get() = implViewModel // 其余原有代码保持不变 }
补充说明
- 你原有代码里传入的
defaultViewModelProviderFactory参数可以省略,使用@AndroidEntryPoint注解的Fragment会自动适配Hilt的ViewModel工厂,无需手动传入。 - 如果项目中有大量类似的接口接收ViewModel的需求,可以自定义封装Kotlin委托来简化重复代码,单个场景使用上述方案即可满足需求,无需额外封装。
内容的提问来源于stack exchange,提问作者Richard Barnard
相关产品推荐
相关产品推荐

