我有一个TabLayout
,由SectionsPagerAdapter
包含三个Fragment
(由同一实例创建(。在片段中,我尝试使用ViewModelProvider.Factory
创建独立的视图模型,然而,我发现所有片段总是使用相同的数据一起更新内容。
我调试过,发现它总是返回相同的视图模型具有差异
BillType
,以及奇怪的是,当进入活动时Factory.create
只被调用一次。
// Log
D/BillType: OUTCOME
D/Factory crate BillType: OUTCOME
D/ViewModel Init BillType: OUTCOME
D/viewModel Bill:BillType: OUTCOME
D/BillType: INCOME
D/viewModel Bill:BillType: OUTCOME
D/BillType: TRANSFER
D/viewModel Bill:BillType: OUTCOME
我不知道哪里出了问题,以前同样的代码运行正确。
class BillViewModel(billType: BillType): ViewModel() {
val bill: MutableLiveData<Bill> = MutableLiveData()
init {
Log.d("ViewModel Init BillType", billType.toString())
bill.value = Bill.QBill().apply {
type = billType
}
}
class NewBillViewModelFactory(val billType: BillType): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
Log.d("Factory crate BillType", billType.toString())
return modelClass.getConstructor(BillType::class.java)
.newInstance(billType)
}
}
}
enum class BillType(val type: Int) {
OUTCOME(0),
INCOME(1),
TRANSFER(2);
}
class NewBillFragment: BaseFragment() {
...
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
billType = BillType.values()[arguments?.getInt(BILLTYPE, 0) ?: 0]
Log.d("BillType", billType.toString())
viewModel = ViewModelProvider(requireActivity(), NewBillViewModel.NewBillViewModelFactory(billType))[NewBillViewModel::class.java]
Log.d("viewModel Bill:BillType", viewModel.bill.value?.type.toString())
_binding = FragmentBillNewBinding.inflate(layoutInflater, container, false)
with(binding) {
data = viewModel
lifecycleOwner = activity
... ui ...
return binding.root
}
companion object {
private const val BILLTYPE = "billtype"
@JvmStatic
fun newInstance(billType: Int): NewBillFragment {
return NewBillFragment().apply {
arguments = Bundle().apply {
putInt(BILLTYPE, billType)
}
}
}
}
}
class SectionsPagerAdapter(private val context: Context, fm: FragmentManager)
: FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment = BillFragment.newInstance(position)
override fun getPageTitle(position: Int): CharSequence = context.resources.getString(TAB_TITLES[position])
override fun getCount(): Int = 3
}
因为您正在使用requireActivity()
创建共享ViewModel
。因此,它将参照Activity
而不是Fragment返回ViewModel
。
如果您想保持ViewModel
片段的作用域,那么您应该将Fragment
作为ViewModelStoreOwner
传递。
viewModel = ViewModelProvider(this, NewBillViewModel.NewBillViewModelFactory(billType))[NewBillViewModel::class.java]