本文目标
理解MVVM架构并能手写出来
强调
首先要强调的一点就是,MVVM并不等同与dataBinding,只不过二者总是混合在一起使用,导致很多人以为dataBinding就是MVVM,其实并不是,dataBinding只是谷歌的一个库,目的是数据和UI的绑定,可以实现单向绑定(数据驱动UI)也能实现双向绑定(数据驱动UI和UI同步数据)
传统MVVM架构
M:Model层,数据模型
V:View层,Activity/Fragment/xml的实例化出来的对象
VM:ViewModel层,就是一个普通的类,用于处理数据相关的业务逻辑,视图显示逻辑,网络请求和其他代码
引用关系
MVVM不像MVC,M<-----> C <------>V
MVC是C层既持有V层又持有M都写到一起,就很臃肿
MVVM是 V--->VM--->M
V层持有ViewModel,ViewModel层持有Model
V层不能直接引用M层,V层和M层是分开的解耦的,V层引用VM层,VM层引用M层,
ViewModel拿到数据后通过接口或者闭包把数据传给V层(如果用了dataBindng,可以用ObservableField等手段)把数据传递给V层
核心思想:MVVM 核心就是为了实现单项依赖关系,省去了接口的定义
代码演示_传统MVVM+dataBinding
在app下的build.gradle中开启
android {
//开启dataBinding
dataBinding{
enabled = true
}
}
V层
public class OldMvvmActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Activity和XML的绑定工作
ActivityOldMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_old_mvvm);
//ViewModel
final HomeViewModel viewModel = new HomeViewModel();
//把viewModel设置给其DataBinding
binding.setViewModel(viewModel);
//获取数据
viewModel.requestData(new HomeViewModel.CallBack() {
@Override
public void onSuccess() {
User user = viewModel.userFiled.get();
Log.d("OldMvvmActivity",user.toString());
}
@Override
public void onFail() {
}
});
binding.editText.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
Log.d("OldMvvmActivity","afterTextChanged: "+viewModel.userFiled.get().address);
}
});
}
}
VM层
public class HomeViewModel {
//被观察者
public ObservableField userFiled = new ObservableField<>();
/**
* 获取数据
*/
public void requestData(CallBack callBack){
User user = new User();
user.name="风清扬";
user.address="address";
if(callBack!=null){
//自动通知预制关联的观察者
userFiled.set(user);
//模拟网络请求,请求成功,然后回调出去,但是并不传递数据,数据是通过ObservableField观察者传递,让V层知道
callBack.onSuccess();
}
}
interface CallBack{
void onSuccess();
void onFail();
}
}
M层
public class User {
public String name;
public String address;
}
jetPack加持下的MVVM
M:Model层,数据模型
V:View层,Activity/Fragment/xml的实例化出来的对象
VM:ViewModel层,要继承JetPack库下的ViewModel 用于处理数据相关的业务逻辑,视图显示逻辑,网络请求和其他代码
JetPack下的MVVM.ViewModel+LiveData组件结合,这样做的目的是既能保证数据不会无缘无故丢失,还能自动关联宿主的生命周期,避免空指针的问题.
代码演示_Jetpack+MVVM
这次就不加dataBinding了
V层
public class JetpackMvvmActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jetpack_mvvm);
TextView tvText = findViewById(R.id.tv_text);
EditText editText = findViewById(R.id.edit_text);
final JetPackViewModel viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(JetPackViewModel.class);
final LiveData liveData = viewModel.getLiveData();
//liveData的数据观察能力来观察数据
liveData.observe(JetpackMvvmActivity.this, new Observer() {
@Override
public void onChanged(User user) {
Log.d("JetpackMvvmActivity",user.toString());
tvText.setText(user.name);
}
});
//editText的输入监控
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
User user = liveData.getValue();
Log.e("JetpackMvvmActivity",user.toString());
}
});
}
}
VM层
public class JetPackViewModel extends ViewModel {
public LiveData getLiveData(){
MutableLiveData liveData = new MutableLiveData<>();
User user = new User();
user.name="令狐冲";
user.address="address";
liveData.postValue(user);
return liveData;
}
}
M层
public class User {
public String name;
public String address;
}
总结
JetPack下的MVVM套路
在VM层创建MutableLiveData然后把数据存到里面,然后用postValue()或者setValue()发送到V层,postValue支持在子线程改变数据 setValue只支持在主线程才能改变数据
在V层,拿到ViewModl对象然后检测数据的改变,然后去进行赋值