[英]ViewModelProvider.Factory always return one viewmodel
I have a TabLayout
, contains three Fragment
(Created by same instance) by SectionsPagerAdapter
.我有一个TabLayout
,包含SectionsPagerAdapter
的三个Fragment
(由同一实例创建)。 Inside the fragment, I try with ViewModelProvider.Factory
to create independent viewmodel, however, I found all fragments always update content together with same data.在片段内部,我尝试使用ViewModelProvider.Factory
创建独立的视图模型,但是,我发现所有片段总是与相同的数据一起更新内容。
I have debugged and found it always return the same viewmodel even with difference
BillType
, and something's weird that when enterence into activity, theFactory.create
is only invoked once.我已经调试过,发现即使有不同的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
I cannot figure out where is wrong, same code runs correctly before.我不知道哪里错了,相同的代码之前运行正确。
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
}
Because you are creating a Shared ViewModel
with requireActivity()
.因为您正在使用requireActivity()
创建共享ViewModel
。 So it will return ViewModel
with reference to Activity
not Fragment.所以它会参考Activity
而不是 Fragment 返回ViewModel
。
If you want to keep ViewModel
Fragment scoped Then you should pass Fragment
as ViewModelStoreOwner
.如果您想保持ViewModel
Fragment 的范围,那么您应该将Fragment
作为ViewModelStoreOwner
传递。
viewModel = ViewModelProvider(this, NewBillViewModel.NewBillViewModelFactory(billType))[NewBillViewModel::class.java]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.