MVP设计模式

传统的MVC(Model、View、Controller)模式,作为View层的Activity或者Fragment,通常背负的任务都非常繁重,不仅要处理View的更新,还要处理耗时的计算等操作,大大降低了代码的可阅读性,甚至有时候改代码会造成一发动全身,各种修修补补,最终导致项目臃肿难以抽离。MVP(Model、View、Presenter)模式能让代码阅读起来更加清晰,我们作为一名程序员,很有必要提升自己的代码编写质量,不仅仅给自己阅读,也要给身边的同事朋友们阅读。

Android开发:一步让你代码质量提升的MVP模式

MVC模式中View层不仅要对数据model处理,还要肩负View的更新,造成代码臃肿,耦合严重。

Android开发:一步让你代码质量提升的MVP模式

MVP模式中将View与model分离,不直接操作数据Model,让Presenter去做相应的计算、耗时操作等,而View就只做些单一的刷新View的操作,大大降低代码的耦合度,MVP模式适合于中小型项目,如果是大型的项目,可考虑用MVVM设计模式。

                                             Android开发:一步让你代码质量提升的MVP模式

好了,废话不多说,多写代码才能悟道其中代码的真理,我就用最简单的例子来开展MVP模式的使用。

第一步

我们先准备两个基础的接口:

IBaseVIew.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : mvp模式中的V层
 */
public interface IBaseView<T> {

}

IBasePresenter.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : mvp设计模式中的P层
 */
public interface IBasePresenter<T> {

    /**
     * 关联activity或fragment
     * @param mvpView
     */
    void attachView(T mvpView);

    /**
     * activity或fragment在destroyed时与View分离
     * 避免耗时操作更新View
     */
    void detachView();
}

                              Android开发:一步让你代码质量提升的MVP模式

第二步

正式使用,建立契约类,我就以排序为例子吧,建一个TestContract.java

TestContract.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : 按谷歌官方推荐指定一个契约类
 */
public interface TestContract {

    interface Presenter extends IBasePresenter<MvpView>{

        void init(int[] array);

        void sort(int[] array, int sort);

    }

    interface MvpView extends IBaseView<Presenter>{

        void sortBefore(String s);

        void sortAfter(String s);

        void showToast(String msg);

    }

}

其中MvpView接口需要我们的Activity或者Fragment去实现,我们在实际开发中可自己编写MvpView的相应方法来处理我们的项目,记得就是MvpView在实现的时间我们尽量保持做View的更新,避免逻辑处理;而Presenter接口由具体的Presenter类来实现,实现具体的逻辑,如:

TestPresenter.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : 测试
 */
public class TestPresenter implements TestContract.Presenter {

    public static final int SORT_SELECT = 0x01;
    public static final int SORT_INSERT = 0x02;
    private TestContract.MvpView mMvpView;

    @Override
    public void init(int[] array) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int item : array) {
            stringBuilder.append(" " + item);
        }
        if (mMvpView != null) {
            mMvpView.sortBefore("排序前:" + stringBuilder.toString());
        }
    }

    @Override
    public void sort(int[] array, int sort) {
        switch (sort) {
            case SORT_SELECT:
                array = selectSort(array);
                break;
            case SORT_INSERT:
                array = insertSort(array);
                break;
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (int item : array) {
            stringBuilder.append(" " + item);
        }
        if (mMvpView != null) {
            mMvpView.showToast(sort == SORT_SELECT ? "选择排序" : "插入排序");
            mMvpView.sortAfter("排序后:" + stringBuilder.toString());
        }
    }

    /**
     * 选择排序
     */
    public int[] selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minPos = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[j] < array[minPos]) {
                    minPos = j;
                }
            }

            if (array[i] > array[minPos]) {
                int temp = array[i];
                array[i] = array[minPos];
                array[minPos] = temp;
            }

        }
        return array;
    }

    /**
     * 插入排序
     */
    public int[] insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int temp = array[i];
            for (int j = i - 1; j >= 0; j--) {
                if (array[j] > temp) {
                    array[j + 1] = array[j];
                    array[j] = temp;
                }

            }
        }
        return array;
    }

    @Override
    public void attachView(TestContract.MvpView mvpView) {
        this.mMvpView = mvpView;
    }

    @Override
    public void detachView() {
        mMvpView = null;
    }

特别提醒

在实现Presenter时记得处理attachView()和detachView()方法,避免View不刷新。

 

最后一步

最后一步当然是我们的Activity实现

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements TestContract.MvpView {

    private TestContract.Presenter testPresenter;
    private int[] array = new int[]{6, 5, 9, 1};
    private TextView tvBefore,tvAfter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testPresenter = new TestPresenter();
        testPresenter.attachView(this);
        tvBefore = findViewById(R.id.tv_array);
        tvAfter = findViewById(R.id.tv_sort_array);
        testPresenter.init(array);
        findViewById(R.id.btn_one).setOnClickListener(onClickListener);
        findViewById(R.id.btn_two).setOnClickListener(onClickListener);
    }

    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_one:
                    testPresenter.sort(array.clone(), TestPresenter.SORT_SELECT);
                    break;
                case R.id.btn_two:
                    testPresenter.sort(array.clone(), TestPresenter.SORT_INSERT);
                    break;
            }
        }
    };


    @Override
    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void sortBefore(String s) {
        tvBefore.setText(s);
    }

    @Override
    public void sortAfter(String s) {
        tvAfter.setText(s);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在销毁的时候分离
        testPresenter.detachView();
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_array"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        android:text="排序前:"
        android:layout_marginBottom="20dp"
        app:layout_constraintBottom_toTopOf="@+id/tv_sort_array"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <TextView
        android:id="@+id/tv_sort_array"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="50dp"
        android:text="排序后:"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@+id/btn_one"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/btn_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="选择排序"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_two"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="150dp"
        android:text="插入排序"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</android.support.constraint.ConstraintLayout>

Android开发:一步让你代码质量提升的MVP模式

 

附带项目传送地址

https://github.com/zhouzhijiang/MvpPrototype

 

结语

简单的介绍和演示了MVP模式的作用以及效果,在日常开发中能有效帮助我们提高自身的coding能力。欢迎大家拍砖点赞分析收藏,谢谢大家。

相关文章:

  • 2021-09-13
  • 2021-09-26
  • 2021-06-08
  • 2021-10-22
  • 2022-12-23
  • 2021-12-27
  • 2021-05-15
  • 2022-02-10
猜你喜欢
  • 2022-02-09
  • 2022-12-23
  • 2022-12-23
  • 2021-09-13
  • 2021-12-23
  • 2021-05-04
  • 2021-04-24
相关资源
相似解决方案