概念性的描述就不写了,直接上代码
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<BaseModel>>(@LayoutRes private val layoutId: Int) :
ViewModelFragment<V, VM>() {
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,同时viewModel中必须持有这个lifecycle对象
return mViewBinding.root //显示页面
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
protected open fun initView(){}
}
其实我的理解就是创建基类将DataBinding和ViewModel的绑定都放在基类中,这样我们创建好基类后,在后续开发中,就按照这个标准去写,省去很多事,接下来就是讲一讲生命周期