viewModel在fragment中使用

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被销毁

你可能感兴趣的:(jetpack)