使用ViewModel和LiveData无法在Fragment间传递数据问题排查
问题原因
你当前的核心问题是两个Fragment各自持有独立的ViewModel实例。在HomeFragment和ListFragment中,你都用ViewModelProvider(this)获取ViewModel,这会让每个Fragment创建专属的ViewModel对象——HomeFragment更新的数据只会存在于自己的ViewModel里,ListFragment的ViewModel还是初始状态,自然始终显示"No Item"。
解决方案
要实现数据共享,需将ViewModel的作用域绑定到两个Fragment所属的Activity上,让它们共用同一个ViewModel实例。只需修改两个Fragment中获取ViewModel的代码,用requireActivity()替代this即可。
修改HomeFragment.kt的ViewModel初始化
将原代码中的ViewModel获取语句替换:
// 原代码 mainViewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java) // 修改后 mainViewModel = ViewModelProvider(requireActivity()).get(MainActivityViewModel::class.java)
完整修改后的HomeFragment.kt:
class HomeFragment : Fragment() { private lateinit var mainViewModel : MainActivityViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragmentHomeBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false) // 绑定到Activity作用域,共享ViewModel实例 mainViewModel = ViewModelProvider(requireActivity()).get(MainActivityViewModel::class.java) binding.viewModel = mainViewModel binding.lifecycleOwner = this binding.tvGroceries.setOnClickListener { mainViewModel.updateItemType(0) it.findNavController().navigate(R.id.action_homeFragment_to_listFragment) } binding.tvElectronics.setOnClickListener { Log.d("sagar", "clicked ") mainViewModel.updateItemType(1) it.findNavController().navigate(R.id.action_homeFragment_to_listFragment) } return binding.root } }
修改ListFragment.kt的ViewModel初始化
同样替换ViewModel获取语句:
// 原代码 mainViewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java) // 修改后 mainViewModel = ViewModelProvider(requireActivity()).get(MainActivityViewModel::class.java)
完整修改后的ListFragment.kt:
class ListFragment : Fragment() { private lateinit var mainViewModel : MainActivityViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragmentListBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_list, container, false) // 绑定到Activity作用域,共享ViewModel实例 mainViewModel = ViewModelProvider(requireActivity()).get(MainActivityViewModel::class.java) binding.viewModel = mainViewModel binding.lifecycleOwner = this return binding.root } }
验证逻辑
修改完成后:
- 点击HomeFragment的按钮时,更新的是Activity作用域下ViewModel的LiveData值
- ListFragment观察的是同一个LiveData对象,数据绑定会自动感知值的变化,更新TextView内容
内容的提问来源于stack exchange,提问作者user20324171
相关产品推荐
相关产品推荐

