多个 Fragment 之间共享数据是很常见的需求,常见的做法是在 Fragment 中通过 Activity 来通知另外另外的 Fragment,或者使用 EventBus 等三方库来实现。
Google 推出的 Jetpack 给我们提供了很多有用的工具,其中 ViewModel 和 LiveData 是最常用的工具之一,通过这两个工具我们可以使用新的姿势来实现 Fragment 之间共享数据。
假设我们需要实现下面的效果,模拟 activity 和 viewpager 中的 Fragment 相互通信, Fragment 中修改数据另外的 Fragment 和 Activity 中跟着一起修改,Activity 中修改数据也能修改 Fragment 中的数据。
首先,我们定义 ViewModel
class ViewModelTestViewModel : ViewModel() {
val data = MutableLiveData(0)
val str = data.map {
it.toString()
}
fun updateData(value: Int) {
data.postValue((data.value ?: 0) + value)
}
}
在 Fragment 中使用,通过 databinding 进行数据绑定,当然不使用 databinding 直接监听 livedata 也是可以的。
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// 这里使用 activity
viewModel = ViewModelProvider(activity!!).get(ViewModelTestViewModel::class.java)
binding.data = viewModel
binding.lifecycleOwner = activity
binding.plus.setOnClickListener {
viewModel.updateData(1)
}
binding.minus.setOnClickListener {
viewModel.updateData(-1)
}
}
注意上面在创建 ViewModel 的时候传的参数是 activity 而不是 Fragment。
在 Activity 中使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(ViewModelTestViewModel::class.java)
binding = DataBindingUtil.setContentView(this, R.layout.view_model_test_activity)
binding.lifecycleOwner = this
binding.data = viewModel
binding.viewPager.adapter = MyAdapter(this)
binding.plus.setOnClickListener {
viewModel.updateData(1)
}
binding.minus.setOnClickListener {
viewModel.updateData(-1)
}
}
这样我们就能实现不同 Fragment 之间数据交互了。
完整代码见 github