如何从另一个Fragment访问共享ViewModel?Kotlin Room集成报错
问题原因分析
你的崩溃根源是两个Fragment的ViewModel作用域不匹配,且NewItemFragment获取ViewModel时未使用自定义Factory:
- TestFragment用
by viewModels()创建的是Fragment自身作用域的ViewModel,存储在Fragment自己的ViewModelStore中,和Activity的ViewModelStore无关 - NewItemFragment调用
ViewModelProvider(requireActivity())时,会去Activity的ViewModelStore查找对应实例,找不到就尝试用默认Factory创建,但你的TestViewModel只有带repository参数的构造函数,系统找不到无参构造,因此抛出NoSuchMethodException
修复步骤
1. 将TestFragment的ViewModel绑定到Activity作用域
把TestFragment中的ViewModel初始化从by viewModels()改为by activityViewModels(),这样ViewModel会被存储在Activity的ViewModelStore中,确保NewItemFragment可以共享同一实例:
class TestFragment : Fragment(), TestItemClickListener { private lateinit var binding: FragmentTestBinding // 改用activityViewModels(),绑定到Activity作用域 private val testViewModel: TestViewModel by activityViewModels { TestItemModelFactory((requireActivity().application as TestApplication).repository) } // ... 其他代码保持不变 }
2. 修改NewItemFragment的ViewModel获取方式
同样使用by activityViewModels()并传入自定义Factory,让系统能正确实例化带参数的ViewModel:
class NewItemFragment(var testItem: TestItem?) : BottomSheetDialogFragment() { private lateinit var binding: FragmentNewItemBinding // 用activityViewModels() + 自定义Factory获取Activity级别的ViewModel private val testViewModel: TestViewModel by activityViewModels { TestItemModelFactory((requireActivity().application as TestApplication).repository) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { binding = FragmentNewItemBinding.inflate(inflater,container,false) // 无需手动调用ViewModelProvider,by activityViewModels()会自动完成初始化 return binding.root } // ... 其他代码保持不变 }
备选方案(不推荐)
如果坚持用lateinit手动初始化ViewModel,必须传入自定义Factory:
testViewModel = ViewModelProvider(requireActivity(), TestItemModelFactory((requireActivity().application as TestApplication).repository) ).get(TestViewModel::class.java)
内容的提问来源于stack exchange,提问作者Snouty
相关产品推荐
相关产品推荐

