前言:
viewModel是什么?有什么作用?
viewModel介于View(视图)和Model(模型数据)之间的这样一个东西,它起到了桥梁的作用,使得视图和数据既能够分离开,也能够保持通信。
MVVM 的本质是 数据驱动,把解耦做的更彻底,viewModel不持有view 。
View 产生事件,使用 ViewModel进行逻辑处理后,通知Model更新数据,Model把更新的数据给ViewModel,ViewModel自动通知View更新界面,而不是主动调用View的方法。
MVVM = Data + View + ViewModel
Data = 数据(本场景点击一次 视为接口返回+1的数据)
View = TestMVVMActivity
ViewModel = TestViewModel
场景举例: 一个按钮 点击后次数累加显示
0.首先导入依赖: 在build.gradle 文件中
dependencies {
... ...
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'//ViewModelProviders
}
1.创建Activity:TestMVVMActivity
class TestMVVMActivity : FragmentActivity() {
var count = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test_mvvm)
var mViewModel = ViewModelProviders.of(this).get(TestViewModel::class.java)
mViewModel.name.observe(this, Observer {
//每次调用mViewModel.setName() 时 会执行这里
test_textview.text = "当前次数:$it"
})
test_textview.setOnClickListener {
mViewModel.setName("" + count++)
}
}
}
2.XML代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".test.TestMVVMActivity">
<TextView
android:id="@+id/test_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0000ff"
android:padding="40dp"
android:text="当前次数:0 (点击增加次数)"
android:textColor="#ffffff"
android:textSize="30sp" />
</LinearLayout>
3.TestViewModel:
class TestViewModel extends ViewModel {
MutableLiveData<String> name = new MutableLiveData();
public MutableLiveData<String> getName() {
return name;
}
public void setName(String name) {
this.name.postValue(name); // 对应响应 getName 的 observe回调
}
}
4.ViewModelFactory (正常情况下不需要用它,假如要用的话代码如下):
public class ViewModelFactory implements ViewModelProvider.Factory {
private TestViewModel mViewModel;
public ViewModelFactory(TestViewModel viewModel) {
this.mViewModel = viewModel;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (modelClass.isAssignableFrom(TestViewModel .class)) {
return (T) mViewModel;
}
throw new IllegalArgumentException("Unknown class name");
}
}
核心思想:
UI界面的显示 与 ViewModel的数据变化 形成了一个显著的 观察者模式
当ViewModel的数据发生变化时,UI自动更新
核心实现是:
TestViewModel 中的 MutableLiveData 变量 // 可被观察数据
以及 setName方法中的 postValue() //数据改变时发通知
以及 TestMVVMActivity中的 mViewModel.name.observe(this, Observer {}) //数据变化时需响应的监听
实际使用场景中:
点击事件中的 mViewModel.setName("" + count++) 就相当于 接口请求后 给 model 赋值的 过程,
这时候 因为接口数据返回,而改变数据 改变UI
注意:
当出现 Cannot create an instance of class TestViewModel class 错误时
在ViewModelProvider构造方法中加Application参数
或使用 ViewModelProvider.AndroidViewModelFactory 类创建 TestViewModel 均无法解决该异常
正确的解决方案是: 新增 自定义的 ViewModelFactory 参数
val mViewModel = ViewModelProvider(this, ViewModelFactory(TestViewModel()) )[TestViewModel::class.java]
为什么没有用DataBinding?
MVVM的缺点(Databinding的缺点):
1.数据绑定增加Bug调试难度
2.对于复杂的页面,model也会很大,虽然使用方便了也很容易保证了数据的一致性,但长期持有,不利于释放内存
3.数据双向绑定不利于View重用
深海个人不建议使用这个弊大于利的笨重框架
如果您有好的建议或者错误纠正,欢迎在评论区一起探讨
如果深海写的东西对您有用,请您给该博客点个赞吧
大家的支持就是深海继续写博客的动力,谢过各位