说明
MVVM模式是指Model-View-ViewModel。相信看过笔者关于MVP的文章的读者也会发现,无论如何抽象化,在我们的View层中是无法避免的要处理一部分逻辑的。而MVVM模式中的View是将View的状态和行为完全抽象化,把逻辑与界面的控制完全交给ViewModel处理.
MVVM由下面三个核心组件组成:
-
Model: 用于获取业务数据模型
-
View: 定义了界面中的布局和外观
-
ViewModel: 逻辑控制层,负责处理数据和处理View层中的业务逻辑
Model层
import java.util.List;/** * Author: loaderman */public class TestEntity { private int code; private String message; private List<ResultBean> result; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public List<ResultBean> getResult() { return result; } public void setResult(List<ResultBean> result) { this.result = result; } @Override public String toString() { return "TestEntity{" + "code=" + code + ", message='" + message + '\'' + ", result=" + result + '}'; } public static class ResultBean { /** * data : {"subTitle":null,"dataType":"TextCard","actionUrl":null,"id":0,"text":"今日社区精选","type":"header5","follow":null,"adTrack":null} * adIndex : -1 * tag : null * id : 0 * type : textCard */ private DataBean data; private int adIndex; private Object tag; private int id; private String type; public DataBean getData() { return data; } public void setData(DataBean data) { this.data = data; } public int getAdIndex() { return adIndex; } public void setAdIndex(int adIndex) { this.adIndex = adIndex; } public Object getTag() { return tag; } public void setTag(Object tag) { this.tag = tag; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return "ResultBean{" + "data=" + data + ", adIndex=" + adIndex + ", tag=" + tag + ", id=" + id + ", type='" + type + '\'' + '}'; } public static class DataBean { /** * subTitle : null * dataType : TextCard * actionUrl : null * id : 0 * text : 今日社区精选 * type : header5 * follow : null * adTrack : null */ private Object subTitle; private String dataType; private Object actionUrl; private int id; private String text; private String type; private Object follow; private Object adTrack; public Object getSubTitle() { return subTitle; } public void setSubTitle(Object subTitle) { this.subTitle = subTitle; } public String getDataType() { return dataType; } public void setDataType(String dataType) { this.dataType = dataType; } public Object getActionUrl() { return actionUrl; } public void setActionUrl(Object actionUrl) { this.actionUrl = actionUrl; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public String getType() { return type; } public void setType(String type) { this.type = type; } public Object getFollow() { return follow; } public void setFollow(Object follow) { this.follow = follow; } public Object getAdTrack() { return adTrack; } public void setAdTrack(Object adTrack) { this.adTrack = adTrack; } @Override public String toString() { return "DataBean{" + "subTitle=" + subTitle + ", dataType='" + dataType + '\'' + ", actionUrl=" + actionUrl + ", id=" + id + ", text='" + text + '\'' + ", type='" + type + '\'' + ", follow=" + follow + ", adTrack=" + adTrack + '}'; } } }}
Respository层
这里使用的网络框架是retrofit+rxjava+okhttp:
public class TestRespository { public void getData(final MutableLiveData<TestEntity> liveData) { HttpServiceDataProvder.getInstence().loadTestData(new HttpCallBack<TestEntity>() { @Override public void onSuccess(TestEntity testEntity) { liveData.setValue(testEntity); } @Override public void onError(Throwable e) { } }); }}
ViewModel层
import androidx.lifecycle.MutableLiveData;import androidx.lifecycle.ViewModel;import com.loaderman.frameappdemo.mvvm.model.TestEntity;import com.loaderman.frameappdemo.mvvm.repository.TestRespository;/** * Author: loaderman */public class TestViewModel extends ViewModel { private final TestRespository testRespository; private MutableLiveData<TestEntity> liveData; public MutableLiveData<TestEntity> getTestEntityLiveData() { if (liveData == null) { liveData = new MutableLiveData<>(); } return liveData; } public TestViewModel() { testRespository = new TestRespository(); } public void getDataFromNet() { testRespository.getData(liveData); }}
View层
<?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="test" type="com.loaderman.frameappdemo.mvvm.model.TestEntity" /> </data> <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/refresh" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mvvm.view.MVVMActivity"> <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@{test.result.toString()}"></TextView> </LinearLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout></layout>
activtiy:
import com.loaderman.frameappdemo.BR;import com.loaderman.frameappdemo.R;import com.loaderman.frameappdemo.databinding.ActivityMvvmBinding;import com.loaderman.frameappdemo.mvvm.model.TestEntity;import com.loaderman.frameappdemo.mvvm.viewmodel.TestViewModel;public class MVVMActivity extends AppCompatActivity { private ActivityMvvmBinding viewDataBinding; private TestViewModel testViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mvvm); viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_mvvm); testViewModel = new ViewModelProvider(this).get(TestViewModel.class); MutableLiveData<TestEntity> testViewModelData = testViewModel.getTestEntityLiveData(); initData(); testViewModelData.observe(this, new Observer<TestEntity>() { @Override public void onChanged(TestEntity testEntity) { viewDataBinding.refresh.setRefreshing(false); viewDataBinding.setVariable(BR.test, testEntity); } }); viewDataBinding.refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { initData(); } }); } private void initData() { viewDataBinding.refresh.setRefreshing(true); testViewModel.getDataFromNet(); }}
效果:
MVVM的优缺点
优点
-
1.双向绑定技术,当Model变化时,View-Model会自动更新,View也会自动变化。很好做到数据的一致性,不用担心,在模块的这一块数据是这个值,在另一块就是另一个值了。所以 MVVM模式有些时候又被称作:model-view-binder模式。
-
2.View的功能进一步的强化,具有控制的部分功能,若想无限增强它的功能,甚至控制器的全部功几乎都可以迁移到各个View上(不过这样不可取,那样View干了不属于它职责范围的事情)。View可以像控制器一样具有自己的View-Model.
-
3.由于控制器的功能大都移动到View上处理,大大的对控制器进行了瘦身。不用再为看到庞大的控制器逻辑而发愁了。
-
4.可以对View或ViewController的数据处理部分抽象出来一个函数处理model。这样它们专职页面布局和页面跳转,它们必然更一步的简化。
缺点
-
第一点:数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
-
第二点:一个大的模块中,model也会很大,虽然使用方便了也很容易保证了数据的一致性,当时长期持有,不释放内存,就造成了花费更多的内存。
-
第三点:数据双向绑定不利于代码重用。客户端开发最常用的重用是View,但是数据双向绑定技术,让你在一个View都绑定了一个model,不同模块的model都不同。那就不能简单重用View了。
Demo学习下载:download.csdn.net/download/jc…
更多学习教程,可以关注【码上加油站】微信公众号,进入Android模块学习哦~