Android MVVM 架构详解

一、前言


MVP 中我们说过随着业务逻辑的增加,UI 的改变多的情况下,会有非常多的跟 UI 相关的 case,这样就会造成 View 的接口会很庞大。而 MVVM 就解决了这个问题,通过双向绑定的机制实现数据和 UI 内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,这样就省去了在 View 层中写很多 case 的情况,只需要改变数据就行。

 

二、MVVM详解


2.1、MVVM 设计图:

 一般情况下就这两种情况,这看起来跟 MVP 好像没啥差别,其实区别还是挺大的。在 MVP 中 View 和 presenter 要相互持有方便调用对方,而在 MVP 中 View 和 ViewModel 通过 Binding 进行关联,他们之前的关联处理通过 DataBinding 完成。

2.2、MVVM 与 DataBinding 的关系

一句话表述就是,MVVM 是一种思想,DataBinding 是谷歌推出的方便实现 MVVM 的工具。在 google 推出 DataBinding 之前,因为xml layout功能较弱,想实现 MVVM 非常困难,而 DataBinding 的出现可以让我们很方便的实现 MVVM。

2.3、DataBinding 简介

DataBinding 是实现视图和数据双向绑定的工具,这里简单介绍下基本用法,详细用法可以参照官方:https://developer.android.com/topic/libraries/data-binding/ 启用DataBinding,只需要在 gradle 文件中添加如下代码:

android {    
    dataBinding{
        enabled true
    }
}

通过 DataBindingUtil 可以动态生成一个 ViewDataBinding 的子类,类名以 layout 文件名大写加 Binding 组成,如:

ActivitySampleMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sample_mvvm);

在 layout 中需要我们配置每个控件绑定的实体对象,以 layout 进行包裹,data 中配置变量名和类型,通过 @{} 或 @={} 的方式进行引用,其中 @={} 的方式表示双向绑定。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data >
        <variable
            name="user"
            type="com.androfarmer.mvvm.model.SampleModel.UserInfo">
        </variable>
    </data>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@={user.name}"/>
    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@={user.age+``}"/>

</LinearLayout>
</layout>

以上为具体在 xml 的用法展示

public static class UserInfo  extends BaseObservable
    {
        private int age;
        private String name;

        @Bindable
        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
            notifyPropertyChanged(BR.age);
        }

        @Bindable
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
            notifyPropertyChanged(BR.name);
        }
    }

为了实现双向绑定还需要对数据实体类做处理,继承 BaseObservable,对读写方法做 @Bindable 和 notifyPropertyChanged 处理。还可以直接使用官方提供的泛型可观察对象 ObservableField,比如: private ObservableField name=new ObservableField<>();

2.4、MVVM Sample

MVVM 跟 MVP 一样,将三层划分的很清楚,Activity 和 xml layout 充当 View,ViewModel 处理业务逻辑以及获取数据,弱化 Model。 很多代码跟前面类似,这里只列出核心代码,ViewModel 层的:

public interface BaseViewModel {
    void onDestroy();
}

public abstract class AbstractViewModel<T extends ViewDataBinding> implements BaseViewModel {
    public T mViewDataBinding;
    public AbstractViewModel(T viewDataBinding)
    {
        this.mViewDataBinding=viewDataBinding;
    }

    @Override
    public void onDestroy() {
        mViewDataBinding.unbind();
    }
}

public class SampleViewModel extends AbstractViewModel<ActivitySampleMvvmBinding> {

    public SampleViewModel(ActivitySampleMvvmBinding viewDataBinding) {
        super(viewDataBinding);
    }

    public  void getUserInfo(String uid, Callback1<SampleModel.UserInfo> callback)
    {
        //从网络或缓存获取信息
        SampleModel.UserInfo userInfo=new SampleModel.UserInfo();
        userInfo.setName("tom");
        userInfo.setAge(18);
        callback.onCallBack(userInfo);
    }
}

ViewMode 层主要处理业务逻辑和获取数据,mViewDataBinding 是通过 View 层传递过来。

 private SampleViewModel mSampleViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivitySampleMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sample_mvvm);
        mSampleViewModel=new SampleViewModel(binding);
        setDataToView();
    }
    private void setDataToView()
    {
        mSampleViewModel.getUserInfo("uid", new Callback1<SampleModel.UserInfo>() {
            @Override
            public void onCallBack(SampleModel.UserInfo userInfo) {
                mSampleViewModel.mViewDataBinding.setUser(userInfo);
            }
        });
    }

xml layout 代码在上面介绍 databing 的用法时已给出,通过上面代码我们就将数据 UserInfo 跟 View 进行绑定了。比如我们更新用户信息,可以直接对 View 上的属性进行修改: mSampleViewModel.mViewDataBinding.tvName.setText("rose"); 也可以通过修改 UserInfo 实体类的字段信息: mSampleViewModel.mViewDataBinding.setUser(userInfo);

从此告别 MVP 中 View 层好多接口的问题,让 View 变得更简洁,修改任何一方,两者都会保持数据同步。

2.5、MVVM 总结

看起来 MVVM 很好的解决了 MVC 和 MVP 的不足,但是由于数据和视图的双向绑定,导致出现问题时不太好定位来源,有可能数据问题导致,也有可能业务逻辑中对视图属性的修改导致。如果项目中打算用 MVVM 的话可以考虑使用官方的架构组件 ViewModel、LiveData、DataBinding 去实现 MVVM。

 

三、关于 MVC、MVP、MVVM 如何选择的探讨

前面在介绍 MVC、MVP、MVVM 时并没有去详细列出他们的优缺点,主要原因有两个:

  1. 网上这方面总结的还是挺多的;
  2. 其实关于架构、设计、模块化等等,它们的优缺点没有绝对的,主要看实现者如何去做。

比如在 mvp 中我们要实现根据业务逻辑和页面逻辑做很多 Present 和 View 的具体实现,如果这些 case 太多,会导致代码的可读性变差。但是通过引入 contract 契约类,会让业务逻辑变得清晰许多。因此不管是用哪种设计模式,只要运用得当,都可以达到想要的结果。 如果非要说怎么选的话,以我浅薄的知识建议如下:

  1. 如果项目简单,没什么复杂性,未来改动也不大的话,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用。
  2. 对于偏向展示型的 app,绝大多数业务逻辑都在后端,app 主要功能就是展示数据,交互等,建议使用 mvvm。
  3. 对于工具类或者需要写很多业务逻辑 app,使用 mvp 或者 mvvm 都可。
  4. 如果想通过一个项目去学习架构和设计模式,建议用MVC然后在此基础上慢慢挖掘改进。最后你可能发现,改进的最终结果可能就变成了 mvp,mvvm。

另外推荐大家阅读:我对移动端架构的思考 - 掘金

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值