一、 MVVM介绍
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。MVVM 的本质是 数据驱动,把解耦做的更彻底,viewModel不持有view 。
二、MVVM主要由三层组成
1. View层
监听UI事件和生命周期,通知到ViewModel;由ViewModel通知数据更新、刷新UI展示。
2. ViewModel层
只负责业务处理,这一点跟MVP的P层功能相同;它不持有View层的应用,这一点跟MVP的P层不相同,MVP的P层会通过View层暴露的接口间接地“持有”对UI控件的引用,而ViewModel层则是完全不会引用到View层的UI控件;
3. Model层
所有的数据处理都在这一层中完成,然后统一暴露给ViewModel使用,例如触发LiveData。
三、使用BataBinding实现简单的MVVM
1、在app的build.gradle里android 里导入dataBinding 如下:
android {
...
dataBinding {
enabled = true
}
}
Android DataBinding - 简书 (jianshu.com)
2、创建Activity类MVVMMainActivity和xml空的l加载dataBinding 布局:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
</LinearLayout>
</layout>
activity:
public class MVVMMainActivity extends AppCompatActivity {
private ActivityMvvmmainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView( this,R.layout.activity_mvvmmain );
}
}
3、实体类
public class User extends BaseObservable {
public String mUserName;
public String mPassWord;
public User(){
}
public User(String mUserName,String mPassWord){
this.mUserName = mUserName;
this.mPassWord = mPassWord;
}
@Bindable
public String getmUserName() {
return mUserName;
}
/**
* @param mUserName */
public void setmUserName(String mUserName) {
this.mUserName = mUserName;
notifyPropertyChanged( BR.mUserName );
}
@Bindable
public String getmPassWord() {
return mPassWord;
}
/**
* @param mPassWord */
public void setmPassWord(String mPassWord) {
this.mPassWord = mPassWord;
notifyPropertyChanged( BR.mPassWord );
}
}
上面添加 @Bindable,作为xml绑定字段
4、创建ViewMode类实现具体业务
public class ViewModel {
private ActivityMvvmmainBinding binding;
public User user;
public ViewModel(ActivityMvvmmainBinding binding,User user){
this.binding = binding;
this.user = user;
}
public void Login(View view){
if (user.getmUserName().equals( "admin" ) && user.getmPassWord().equals( "12345" )){
Log.d( "TAG","success" );
Toast.makeText(binding.login.getContext(),"success",Toast.LENGTH_SHORT).show();
}else {
Log.d( "TAG","fail" );
Toast.makeText(binding.login.getContext(),"fail",Toast.LENGTH_SHORT).show();
}
}
}
5、在activity和布局里进行绑定
public class MVVMMainActivity extends AppCompatActivity {
private ActivityMvvmmainBinding binding;
private User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView( this,R.layout.activity_mvvmmain );
user = new User( "admin","12345" );
binding.setViewmodel( new ViewModel( binding,user ));
}
}
完整的xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.ecactus.androidappframework.mvvm.model.User" />
<variable
name="viewmodel"
type="com.ecactus.androidappframework.mvvm.viewmodel.ViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="40dp"></LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingLeft="30dp"
android:text="账号密码登录"
android:textColor="#000000"
android:textSize="30sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal">
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名"
android:paddingLeft="10dp"
android:singleLine="true"
android:text="@={viewmodel.user.mUserName}"
android:textColor="#ff000000"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp">
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:hint="密 码"
android:paddingLeft="10dp"
android:password="true"
android:text="@={viewmodel.user.mPassWord}"
android:textColor="#ff000000"
android:textSize="15sp" />
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="80dp"
android:layout_marginTop="10dp"
android:background="#1A73E8"
android:onClick="@{viewmodel.Login}"
android:text="登录"
android:textColor="#ffffff"
android:textSize="15sp" />
</LinearLayout>
</layout>