viewModel在frgamnet中使用,如果使用activity例如
viewModelFragment = ViewModelProviders.of(requireActivity()).get(ChooseAreaViewModel::class.java)
这种方式和在activity中使用相同参考viewModel源码
如果使用
viewModelFragment = ViewModelProviders.of(this).get(ThirdFragmentViewModel::class.java)
class MVVMActivity:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_mvvm)
//让FragmentManager日志显示
FragmentManager.enableDebugLogging(true)
val secondFragment = SecondFragment.newInstance()
val thirdFragment = ThirdFragment.newInstance()
button2.setOnClickListener {
val ft = supportFragmentManager.beginTransaction()
ft.replace(R.id.fl,secondFragment)
ft.commit()
}
button3.setOnClickListener {
val ft = supportFragmentManager.beginTransaction()
ft.replace(R.id.fl,thirdFragment)
ft.commit()
}
}
}
class ThirdFragment:Fragment() {
private lateinit var viewModelFragment:ThirdFragmentViewModel
companion object{
fun newInstance(): ThirdFragment{
return ThirdFragment()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModelFragment = ViewModelProviders.of(this).get(ThirdFragmentViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_mvvm_third,container,false)
}
}
class SecondFragment:Fragment() {
private lateinit var viewModelFragment:ChooseAreaViewModel
companion object{
fun newInstance(): SecondFragment{
return SecondFragment()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModelFragment = ViewModelProviders.of(this).get(ChooseAreaViewModel::class.java)
}
}
这里直接分析fragment.getViewModelStore()
public ViewModelStore getViewModelStore() {
if (mFragmentManager == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
return mFragmentManager.getViewModelStore(this);
}
首先调用FragmentManagerImp.getViewModelStore方法
ViewModelStore getViewModelStore(@NonNull Fragment f) {
return mNonConfig.getViewModelStore(f);
}
然后调用fragmentManagerViewModel的getViewModelStore方法
ViewModelStore getViewModelStore(@NonNull Fragment f) {
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore == null) {
viewModelStore = new ViewModelStore();
mViewModelStores.put(f.mWho, viewModelStore);
}
return viewModelStore;
}
这里首先从mViewModelStores中获取,mViewModelStores是一个hashMap如果没有获取到则创建ViewModelStore,并添加到mViewModelStores中,这里得到ViewModelStore后和在activity处理方式相同,首先从ViewModelStore中获取ViewModel,如果没有获取到则创建ViewModel并添加到ViewModelStore中
清除方法则是使用fragmentManagerViewModel的clearNonConfigState方法
void clearNonConfigState(@NonNull Fragment f) {
if (FragmentManagerImpl.DEBUG) {
Log.d(FragmentManagerImpl.TAG, "Clearing non-config state for " + f);
}
// Clear and remove the Fragment's child non config state
FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho);
if (childNonConfig != null) {
childNonConfig.onCleared();
mChildNonConfigs.remove(f.mWho);
}
// Clear and remove the Fragment's ViewModelStore
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore != null) {
viewModelStore.clear();
mViewModelStores.remove(f.mWho);
}
}
当fragment处于移除状态时才会调用该方法,例如在activity中fragment切换使用replace方法,activity被销毁例如调用finish方法,或者使用viewPage的adapter是FragmentStateAdapter,此时fragment在切换一定数量后被销毁(fragment会走onDestory方法),则会调用clearNonConfigState
当fragment不在移除状态则不会调用clearNonConfigState方法。例如在activity中fragment切换使用add方法添加hide方法隐藏,或者屏幕旋转,或者使用viewPage的adapter是FragmentPagerAdapter,此时fragment在切换一定数量后不会被销毁(fragment只会走到onDestoryView方法),由于不会调用clearNonConfigState方法故ViewModelStore可以一直保存,直到其所在的activity被销毁