Android之JetPack_MVVM开发模式

494 阅读4分钟

说明

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模块学习哦~