Android之Mvc、Mvp、Mvvm

1.Mvc模式

三层模型Model-View-Control,我们可以把一个xml布局看作一个View,Activity或者Fragment看作一个Control,Model由相关的数据操作类来承担,平时一般代码最常用写法。

使用总结:

  • 由于xml布局限制,Activity某种意义上充当了controller和view这2层,controller和view层无法解耦
  • 逻辑代码上数据业务逻辑尽量在Mode层处理,比如接口请求采用回调形式提供方法给Activity调用,其他业务功能尽量封装工具类供Activity使用,这样才能更好的扩展业务,代码灵活性更高

2.Mvp模式

Model-View-Presenter三层,Model和View之间不进行通讯,Presenter持有View与Model处理业务逻辑,实现了Controller和View解耦。Mvp是目前主流开发模式,下面通过Google Mvp Demo步步分析。

Model层

主要是模拟接口请求回调,我们快速过。

/**
 * 模拟请求接口数据
 *
 * @author zhukui
 */
public class MvpModel {

    /**
     * 模拟获取数据
     */
    public void getData(final IHttpCallBack callBack) {
        HttpUtil.requestData(callBack);
    }
}

View层

定义BaseView,Fragment继承BaseView。

/**
 * BaseView
 *
 * @author zhukui
 */
public interface BaseView<P extends BasePresenter> {
    void setPresenter(P presenter);

    boolean isActive();
}
/**
 * MvpFragment
 *
 * @author zhukui
 */
public class MvpFragment extends Fragment implements MvpContract.View {

    private static final String ARG_PARAM_1 = "param_1";

    private String mParam1;

    private TextView mTextView;

    private MvpContract.Presenter mPresenter;

    public static MvpFragment newInstance(String param1) {
        MvpFragment fragment = new MvpFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM_1, param1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM_1);
        }
        //初始化presenter
        mPresenter = new MvpPresenterImpl(this);
        setPresenter(mPresenter);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_mvp, container, false);
        mTextView = view.findViewById(R.id.tv_result);
        final Button button = view.findViewById(R.id.btn_get_data);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.getData();
            }
        });
        return view;
    }

    @Override
    public void onStart() {
        super.onStart();
        mPresenter.start();
        mPresenter.getData();
    }

    @Override
    public void showLoading() {
        Toast.makeText(getContext(), "Loading...", Toast.LENGTH_LONG).show();
    }

    @Override
    public void refreshUI(String result) {
        mTextView.setText(result);
    }

    @Override
    public void showError() {

    }

    @Override
    public void setPresenter(MvpContract.Presenter presenter) {
        mPresenter = presenter;
    }

    @Override
    public boolean isActive() {
        return isAdded();
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mPresenter.detachView();
    }
}

Presenter层

定义BasePresenter和其实现类MvpPresenterImpl,这里实现了Presenter持有弱引用View,并在页面detach时清空持有的弱引用View

/**
 * BasePresenter
 *
 * @author zhukui
 */
public interface BasePresenter {
    void start();
}
/**
 * PresenterImpl - 实现业务逻辑并刷新页面
 *
 * @author zhukui
 */
public class MvpPresenterImpl<V extends MvpContract.View> implements MvpContract.Presenter {

    /**
     * Presenter持有弱引用View,并在页面detach时清空持有的弱引用View
     */
    protected WeakReference<V> mView;
    protected MvpModel mMvpModel;

    public MvpPresenterImpl(V view) {
        mView = new WeakReference<V>(view);
        view.setPresenter(this);
        mMvpModel = new MvpModel();
    }

    protected boolean isViewActive() {
        return mView != null && mView.get().isActive();
    }

    @Override
    public void detachView() {
        if (mView != null) {
            mView.clear();
            mView = null;
        }
    }

    @Override
    public void getData() {
        if (!isViewActive()) {
            return;
        }
        mMvpModel.getData(new IHttpCallBack<String>() {
            @Override
            public void onSuccess(String s) {
                mView.get().refreshUI("success");
            }

            @Override
            public void onError(String error) {
                mView.get().refreshUI("error");
            }
        });
    }

    @Override
    public void start() {
        if (!isViewActive()) {
            return;
        }
        mView.get().showLoading();
    }
}

Contract契约类

 Google MVP契约类,用于定义同一个界面的view和presenter的接口,通过规范的方法命名或注释,可以清晰的看到整个页面的逻辑。
/**
 * Contract 契约类
 * <p>
 * Google MVP契约类,用于定义同一个界面的view和presenter的接口,
 * 通过规范的方法命名或注释,可以清晰的看到整个页面的逻辑。
 *
 * @author zhukui
 */
public interface MvpContract {

    interface Presenter extends BasePresenter {
        /**
         * 获取数据
         */
        void getData();

        /**
         * 拆卸View
         */
        void detachView();
    }

    interface View extends BaseView<Presenter> {
        /**
         * 显示加载中
         */
        void showLoading();

        /**
         * 刷新界面
         */
        void refreshUI(String result);

        /**
         * 显示错误界面
         */
        void showError();
    }
}

使用总结:

  • mvp模式,实现了model与view的解耦,Presenter处理业务逻辑
  • Presenter跟View相互持有,导致View页面关闭时Presenter层可能有异步线程正在工作,从而导致页面释放不了,解决方法:Presenter持有弱引用View,并在页面detach时清空持有的弱引用View。
  • 业务逻辑非常复杂的页面,Presenter层、View层接口会很多很庞大,难以维护。

3.Mvvm模式

View-ViewModel-View三层,通过双向绑定的机制,实现了数据和UI一方改变另一方能够及时更新。谷歌Mvvm框架中View和ViewModel通过Binding进行关联,并通过DataBinding完成双向绑定。MVVM代码结构如下:

 dataBinding配置

在build.gradle文件android标签下增加dataBinding代码。

android {    
    dataBinding{
        enabled true
    }
}

Model层

模拟接口请求,这里直接跳过。

View层

A.xml布局设置

指定了当前页面的Model对象,用layout包裹,data中配置Model对象变量名和Model对象路径,通过@{}或@={}的方式进行引用,其中@={}的方式表示双向绑定。

<?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>
        <!--绑定ViewModel-->
        <variable
            name="viewModel"
            type="com.android.zk.mvvm.viewmodel.MvvmViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn_getAccount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:onClick="@{viewModel.getData}"
            android:text="获取数据" />

        <TextView
            android:id="@+id/tv_getResult"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.result}" />

    </LinearLayout>

</layout>

B.activity设置

ActivityMvvmBinding为同步代码后自动生成类,activity中实现了View与ViewModel绑定。

/**
 * Mvvm模式
 * <p>
 * 说明:简单使用,后续会完善使用
 *
 * @author zhukui
 */
public class MvvmActivity extends AppCompatActivity {

    private ActivityMvvmBinding binding;
    private MvvmViewModel mvvmViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //替换setContentView
        binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvm);
        mvvmViewModel = new MvvmViewModel(getApplication(), binding);
        //初始化viewModel
        binding.setViewModel(mvvmViewModel);
    }

}

ViewModel层

ViewMode层主要处理业务逻辑,binding是传递过来的,实现双向绑定需要继BaseObservable,对读方法用@Bindable处理,写方法用notifyPropertyChanged处理,其中BR为自动生成。

/**
 * ViewModel
 *
 * @author zhukui
 */
public class MvvmViewModel extends BaseObservable {

    private ActivityMvvmBinding binding;
    private MvvmModel mvvmModel;
    private String result;

    @Bindable
    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
        notifyPropertyChanged(BR.result);
    }

    public MvvmViewModel(Context context, ActivityMvvmBinding binding) {
        this.binding = binding;
        mvvmModel = new MvvmModel();
        setResult("success");
    }

    public void getData(View view) {
        mvvmModel.getData(new IHttpCallBack<String>() {
            @Override
            public void onSuccess(String success) {
                setResult(success);
            }

            @Override
            public void onError(String error) {
                setResult(error);
            }
        });
    }
}

使用总结:

  • MVVM中Activity和xml布局充当View,ViewModel处理业务逻辑以及获取数据,弱化Model。
  • MVVM解决MVP中V层、P层好多接口的问题,让View变得更简洁,修改任何一方,两者都会保持数据同步。
  • 缺点:数据和视图的双向绑定,导致出现问题时不太好定位问题来源,有可能是数据、视图属性更改导致。

源码传送:androidMvcMvpMvvm

### 回答1: MVCMVPMVVM 是三种设计模式,用于在 Android 应用程序中组织代码。 MVC(模型-视图-控制器):模型存储应用程序数据,视图显示数据,控制器处理用户交互。 MVP(模型-视图-presenter):与 MVC 类似,但 presenter 更加紧密地与视图绑定,负责更新视图。 MVVM(模型-视图-视图模型):与 MVP 类似,但视图模型与视图绑定,负责将数据转换为视图可用的形式。 三者的差异在于MVC会产生视图和模型之间的耦合,MVPMVVM是将视图和模型之间的耦合分离,更加灵活。 ### 回答2: Android开发中,MVCMVPMVVM都是常见的架构模式,用来组织Android应用的代码结构,让代码更加规范、易于维护。 MVC(Model-View-Controller)是最早的一种架构模式,它将应用分为三个模块:模型(Model)、视图(View)和控制器(Controller)。其中模型负责数据的存储和操作,视图负责显示界面,控制器则负责对用户输入进行响应,协调模型和视图之间的关系。MVC模式的优点是结构清晰,各个模块职责分明,易于实现代码复用,因此广泛应用。但是MVC模式也有一些缺点,比如控制器中很难进行单元测试,代码复杂度较高,难以维护大型项目等问题。 MVP(Model-View-Presenter)是一种基于MVC模式的进,它将模型和视图分离,通过在中间加上Presenter来连接两者。Presenter接受用户的输入,并根据视图的状态更新数据模型,然后更新视图显示。MVP模式的优点是易于单元测试,将业务逻辑和界面分离,代码复杂度较低,易于维护。但是对于大型项目,Presenter层也会变得庞大且复杂。 MVVM(Model-View-ViewModel)是一种结合数据绑定和命令模式的前端设计模式,它将模型、视图和ViewModel分开,通过数据绑定将视图和ViewModel联系起来。ViewModel封装了视图的状态和行为,当ViewModel被修时,视图会自动更新。MVVM模式的优点是将视图和ViewModel解耦,通过数据绑定自动更新视图,提高了代码的可重用性。但MVVM模式需要使用大量的数据绑定,可能导致系统卡顿,同时实现较为复杂。 总的来说,MVCMVPMVVM这三种模式都有各自的适用场景。在小型项目中,可以使用MVC模式;在中型项目中,可以使用MVP模式;在大型项目中,可以使用MVVM模式。选择合适的架构模式能够让代码更易于维护,提高开发效率。 ### 回答3: Android是一种以Java为基础的开源操作系统,广泛应用于移动设备中。在开发Android应用程序时,常用的三种架构模式是MVCMVPMVVMMVC是一种典型的应用程序架构模式,其中M代表模型,V代表视图,C代表控制器。在Android中,MVC通常用规定ViewController或Activity来实现。 MVP是Model-View-Presenter的缩写,其中M代表模型,V代表视图,P代表演示者。MVP将视图项分离,并引入中间者Presenter,以实现界面和业务逻辑分离的目的。在Android中,MVP通常实现在Activity或Fragment上。 MVVM是Model-View-ViewModel的缩写,其中M代表模型,V代表视图,VM代表视图模型。ViewModel担任中间件角色,处理视图中的数据,并使控制逻辑与视图分离开。在Android中,MVVM通常实现了Data Binding。 总的来说,三种架构模式都旨在将应用程序分离成各个组成部分,每个部分具有各自分离的职责,在开发Android应用程序时选择合适的架构模式,能够提高开发效率、提高代码质量、降低维护成本、提高整个应用程序的可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值