主要是统一下在AppCompatActivity获取ViewModel+ViewBinding的入口,先看下最终的封装效果:

下面就让我们一步步的实现下这种效果:
BaseMvvmActivityabstract class BaseMvvmActivity() : AppCompatActivity() {}
这个类继承了AppCompatActivity,将作为之后界面继承的的基类,在这个类中统一获取ViewModel+ViewBinding的入口。
ViewBinding的获取入口ViewBinding的具体创建函数是ViewBinding.inflate(),首先我们要明确一个点,函数和函数类型是可以相互转化的:
private val vb: (LayoutInflater) -> ActivityMainBinding = ActivityMainBinding::inflate
我们将这个创建函数转换成一个函数类型并作为构造参数传入BaseMvvmActivity,其次还要在BaseMvvmActivity中传入<T: ViewBinding>,这样才能够获取ViewBinding的具体实现类型:
abstract class BaseMvvmActivity<T: ViewBinding>(
private val vb: (LayoutInflater) -> ActivityMainBinding
): AppCompatActivity() {
protected lateinit var mBinding: VB
}
然后重写onCreate()方法,在该方法中完成具体ViewBinding的创建以及当前界面根布局的设置:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = vb(layoutInflater)
setContentView(mBinding.root)
}
这样我们就可以在界面内中这样使用:
class ZygoteActivity : BaseMvvmActivity<ActivityMainBinding>(
ActivityMainBinding::inflate
) {
fun test2() {
//直接从父类中获取ViewBinding的实现对象
mBinding.iconIv.visibility = View.VISIBLE
}
}
请注意,Fragment可不能进行如此封装,因为如果把ViewBinding的创建函数作为构造函数的一个参数传入,但Fragment创建销毁被重建后,该参数就直接丢失了,这就会造成后续在onCreateView()方法中调用该参数创建ViewBinding时直接空指针异常了。
ViewModel的获取入口对于ViewModel的创建,我们只需要拿到具体要创建ViewModel的class对象即可,那我们就可以将这个class对象直接通过构造参数传入到BaseMvvmActivity中即可:
abstract class BaseMvvmActivity<VB : ViewBinding, VM : ViewModel>(
private val vb: (LayoutInflater) -> VB, private val vmClass: Class<VM>
) : AppCompatActivity() {
}
在BaseMvvmActivity中通过懒加载的形式完成具体ViewModel的创建:
protected val mViewModel: VM by lazy {
ViewModelProvider(viewModelStore, defaultViewModelProviderFactory).get(vmClass)
}
然后就可以这样使用:
class ZygoteActivity : BaseMvvmActivity<ActivityMainBinding, MainViewModel>(
ActivityMainBinding::inflate,
MainViewModel::class.java
) {
fun test2() {
mBinding.iconIv.visibility = View.VISIBLE
//使用ViewModel
mViewModel.data1.observe(this) {
}
}
}
请注意,如果要创建的具体ViewModel的构造方法带有参数,请重写AppCompatActivity的getDefaultViewModelProviderFactory方法,实现ViewModelProvider.Factory接口自定义一个ViewModel的创建工厂并返回即可。
经过上面的封装,我们就可以实现文章一开始使用的那种效果,使用起来也是很简单,除了传入的构造参数写起来稍微有一丢丢麻烦,看起来不美观哈!!
阅读量:1959
点赞量:0
收藏量:0