MVVM是一种设计思想,它是Model-View-ViewModel
的缩写。它也是MVC
的增强版。
Model
是代表数据模型,也可以在Model
中定义数据修改和操作的业务逻辑。用于进行业务处理View
是代表UI组件,它负责将数据模型转化成UI展现出来。对应的是Activity等ViewModel
是一个同步View和Model的对象。作为Model和View的桥梁
MVVM采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,model中数据变化也将会自动展示在页面上。把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所谓的数据-视图分离,数据不会影响视图。
demo实现
1.定义Model --用于处理具体逻辑
public class MvvmModel { public void login(String phone,String pass,CallBack callBack){ if (pass.equals("1234")&&phone.equals("1234")){ callBack.onSuccess(); }else callBack.onFailed(); } }
2.定义view---包含 ViewModel实例
public class MainActivity extends AppCompatActivity { ActivityMainBinding mMainBinding; ViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); viewModel = new ViewModel(getApplication(),mMainBinding); //获取VM实例 mMainBinding.setViewModel(viewModel); mMainBinding.setPass("1234"); mMainBinding.setPhone("1234"); ButtonClick buttonClick = new ButtonClick(); buttonClick.setViewModel(viewModel); mMainBinding.setButtonClick(buttonClick); } }
3.定义ViewModel--用于从view获取数据,并将数据传给model执行对应的逻辑,包含model
public class ViewModel extends BaseObservable { private MvvmModel mvvmModel; ActivityMainBinding binding; Application application; public ViewModel() { mvvmModel=new MvvmModel(); } ButtonClick mButtonClick; public ViewModel(Application application, ActivityMainBinding binding) { mButtonClick = new ButtonClick(); this.application=application; mvvmModel=new MvvmModel(); this.binding=binding; } public String getPhone(){ return binding.etPhone.getText().toString(); } public String getPass(){ return binding.etPass.getText().toString(); } public void toast(String info){ Toast.makeText(application, info, Toast.LENGTH_SHORT).show(); } public void login(){ Log.e("TAG","login"); mvvmModel.login(getPhone(), getPass(), new CallBack() { @Override public void onSuccess() { toast("onSuccess"); } @Override public void onFailed() { toast("onFailed"); } }); } }
其他代码如下
public interface CallBack { void onSuccess(); void onFailed(); }
public class ButtonClick implements View.OnClickListener{ ViewModel mViewModel ; public void setViewModel(ViewModel viewModel) { mViewModel = viewModel; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.login: mViewModel.login(); break; } } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="phone" type="String" /> <variable name="pass" type="String" /> <variable name="ViewModel" type="com.example.mvvm.ViewModel" /> <variable name="ButtonClick" type="com.example.mvvm.ButtonClick" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.textfield.TextInputLayout app:layout_constraintTop_toTopOf="parent" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/etl_phone"> <EditText android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/et_phone" android:text="@{phone}" android:hint="请输入手机号" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout app:layout_constraintTop_toBottomOf="@id/etl_phone" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/etl_pass"> <EditText android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/et_pass" android:text="@{pass}" android:inputType="textPassword" android:hint="请输入密码" /> </com.google.android.material.textfield.TextInputLayout> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/login" android:text="登录" android:onClick="@{ButtonClick::onClick}" app:layout_constraintTop_toBottomOf="@id/etl_pass"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>