概念性的描述就不写了,直接上代码
MVVM框架,主要是构建基类,实现ViewModel绑定,ViewBinding的绑定,在构建好基类后,后续开发中新建activity或fragment的viewModel和viewBinding就会在基类的方法中实现绑定
1.新建一个抽象类Repository,仓库类,网络请求或者从本都读取缓存都仓库类的实现类中处理
2.新建一个BaseViewModel抽象类,继承自ViewModel,如果要在viewModel中使用Application,那么就继承AndroidViewModel,因为AndroidViewModel的构造函数中,必须传入一个Application
我这里选择了传入了一个BaseRepository的对象,也就是对应的仓库,从仓库中获取数据,在ViewModel中使用liveData
3.1.创建fragment绑定ViewBinding的抽象类,在这个类中获取每个fragment的xml文件的DataBinding
3.2.创建一个抽象BaseFragment类,继承ViewBindingFragment,并且在BaseFragment类中实现ViewModel的绑定
4.1.同上,创建一个ViewBindingActivity的抽象类,作用也是获取activity xml的viewBinding
4.2.创建一个BaseActivity的抽象类,继承ViewBindingActivity,作用就是在BaseActivity中绑定ViewModel
使用就很简单了,如果你的fragment中不涉及到数据请求获取,不需要创建ViewModel,那么直接继承ViewBingFragment,这样省的要在fragment中对xml里面的空间id进行findViewById,也能实现数据双向绑定,如果涉及到数据请求,那么就继承BaseFragment,创建一个当前fragment对应的viewModel,利用liveData的特性,在fragment中,只需要注册liveData的观察者就能接收到数据的更新
---------------------------------------------------------------------------------------------------------------------------------
kotlin版本的mvvm,其实思路写法和java版本的一样,只是一些语法的不同
1.创建ViewModel基类
2.在java版本中,我们是先实现dataBinding,在kotlin中我们先来实现ViewModel的绑定
- /**
- * 带databinding和BaseViewModel的fragment
- * dataBinding就是各个fragment自己布局的binding
- * VM就是给每个fragment创建的ViewModel
- * 其实这个类,就是相当于抽象工厂模式,封装了构造ViewModel的方法
- */
- abstract class ViewModelFragment<V : ViewBinding, VM : BaseViewModel<BaseModel>> : Fragment() {
- private val TAG = javaClass.simpleName
- protected lateinit var mViewBinding: V
- protected lateinit var mViewModel: VM
-
- //定义一个获取dataBinding的抽象函数,子类可重写此函数,构造dataBinding
- abstract fun initBinding(inflater: LayoutInflater, container: ViewGroup?): V
-
- /**
- * 每个视图,都要持有一个ViewModel
- * 这里是给每个视图绑定viewModel
- * 将子类的ViewModel传进来绑定ViewModel
- */
- @Suppress("UNCHECKED_CAST")
- fun initViewModel(viewModelStoreOwner: ViewModelStoreOwner): VM {
- var modelClass: Class<VM>?;
- val type: Type? = javaClass.genericSuperclass
- modelClass = if (type is ParameterizedType) {
- type.actualTypeArguments[1] as Class<VM>
- } else {
- null
- }
-
- if (modelClass == null) {
- modelClass = BaseModel::class.java as Class<VM>
- }
- //最终目的就是创建ViewModel,绑定了ViewModel的生命周期,也就是在这里,viewModel持有了lifecycle的对象
- return ViewModelProvider(
- viewModelStoreOwner,
- ViewModelProvider.AndroidViewModelFactory(BaseApplication.getInstance())
- )[modelClass]
- }
-
- /**
- * 绑定ViewModel
- */
- fun <T:ViewModel> obtainViewModel(viewModelClass : Class<T>)=
- ViewModelProvider(
- viewModelStore,
- ViewModelProvider.AndroidViewModelFactory(BaseApplication.getInstance())
- )[viewModelClass]
-
- }
注释应该很清晰了,我们在ViewModelFragment中,创建了一个抽象函数,子类重写后获取DataBinding,至于ViewModel的构造和绑定,我们在此类中已经写好,子类直接调用就能绑定ViewModel。再创建一个BaseFragment继承ViewModelFragment,在BaseFragment中就做两件事:1.调用initViewModel将ViewModel和自己绑定;2.重写initBinding获取dataBinding
- /**
- * 继承自ViewModelFragment
- * 做两件事情:1、重写initBinding;2、调用initViewModel
- */
- abstract class BaseFragment<V : ViewBinding, VM : BaseViewModel
>>(@LayoutRes private val layoutId: Int) : - ViewModelFragment
() { -
- protected val TAG = BaseFragment::class.java.simpleName
-
- protected val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
- override fun handleMessage(msg: Message) {
-
- }
- }
-
- /**
- * 抽象工厂类定义的业务方法
- * 本类相当于工厂类,要实现这些方法
- * 根据xml的id layoutId构建ViewBinding
- */
- override fun initBinding(inflater: LayoutInflater, container: ViewGroup?): V =
- DataBindingUtil.inflate(inflater, layoutId, container, false)
-
- /**
- * 这里是将xml的id layoutId绑定给对应的fragment,也就是fragment展示的页面
- */
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- mViewBinding = initBinding(inflater, container) //调用构建viewBinding获取到viewBinding
- mViewModel = initViewModel(this) //获得viewModel,这里的viewModel是绑定了当前fragment的生命周期的
- lifecycle.addObserver(mViewModel) //观察者模式,lifecycle就是被观察者,持有一个观察者集合List
,当状态发生改变,通知这个集合里的ViewModel,同时viewModel中必须持有这个lifecycle对象 -
- return mViewBinding.root //显示页面
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- initView()
- }
-
- protected open fun initView(){}
- }
其实我的理解就是创建基类将DataBinding和ViewModel的绑定都放在基类中,这样我们创建好基类后,在后续开发中,就按照这个标准去写,省去很多事,接下来就是讲一讲生命周期