适用于小型项目的 Android MVP 架构

MVP 架构介绍

其实没什么好介绍的了,网上有很多相关的文章,我就不去 copy 了,反正就是 Google 公司推出的一个适合中大型 Android 项目开发的架构。
之前做了一个项目使用的就是 MVP 架构,通过这么久的使用总结发现 MVP 并不适合小型项目。用过的人都知道,MVP 架构要求接口繁多,一个简单的 Activity 本来一两个类就能解决,用了 MVP 之后类数量瞬间激增,有点过度设计的意思。所以 MVP 对于很多人来说可能有点鸡肋了,那本篇文章就针对这个问题提出一个自认为还不错的解决方案: 使小型项目也可以很自然的使用 MVP 架构,实现高内聚,低耦合。

设计思想

首先将项目中常用的功能提取出来封装成一个 MVP 模块,这个模块完全由 MVP 来实现,其他地方无所谓。 每个 MVP 模块专注自己的职能,遵守单一职责原则。在每个需要使用这个功能的地方实现对应的接口即可。

MVP 一般使用介绍

MVP 中分三层:
1. M:Model,数据交互层;
2. P:Presenter,逻辑控制层;
3. V:View,界面显示层。
在一般情况下我们可以按照下图的显示的关系使用 MVP:

MVP 架构图


如上图所示,View 层只同 Presenter 层通信,负责界面的展示及事件的触发控制;Presenter 层与 View 层及 Model 层通信,负责业务逻辑的处理:包括更新 View 层界面各事件的处理,及从 Model 层获取数据;Model 层与 Presenter 层通信,负责数据的处理,如从网路获取数据。各层次之间通过接口耦合。

具体实现

首先我们设想一个这样的场景,在一个月黑风高的夜晚,产品经理提了个需求:在每个产品展示界面都加一个筛选按钮,筛选按钮的内容从后台获取。一般来说,我们按照如下方式来使用 MVP,首先看包结构:

包结构


如上图所示,IProduceView 提供了用于控制 Activity 的接口,ProducePresenterImpl 实现了 IProducePresenter 接口,其中持有一个 IProduceView 对象和 IProduceModel 对象,ProduceModelImpl 实现了 IProduceModel 接口,并持有一个 IProducePresenter 接口。通过这种方式降低模块之间的解耦度,不同模块使用接口通信。
当产品经理提出了这个需求之后,M、V、P 三层的代码都要修改,当产品列表界面只有一个时这样还好,但是如果有十个这样的界面呢?难道我们要在每一个界面都写一遍重复代码?另外如果只是个简单的功能还好,如果是个比较复杂的功能呢?不仅代码量变多,还都是重复性代码,这简直是程序员最讨厌的事情。另外在小项目中使用 MVP 不仅会使原本简单的界面变得复杂,还会增加类数量,下面我就来介绍一下今天我要说的 MVP 架构。

在小项目中使用 MVP

我的想法是,小项目或者简单的地方按照原有的架构如 MVC 不变,只需要把其中复杂或常用的模块提取出来使用 MVP 来实现,因为 MVP 架构的思想之一就是代码重用,我们把重复性代码提取出来正好也实现了这个想法。接着上面的需求,我们把项目改成如下模式:

扫描二维码关注公众号,回复: 1941280 查看本文章
修改后的包结构


修改之后的包结构新增了一个 Filter 包,其内为筛选功能的代码,包括业务逻辑,数据交互,但不包括具体显示,只提供了一个 IFilterView 接口,需要使用筛选功能的界面只需要实现这个接口即可。废话说了这么多,现在直接来看代码:

package com.zhangke.androidmvp.Filter.view;

import com.zhangke.androidmvp.Filter.entity.ProduceTypeEntity;

import java.util.List;

/**
 * 筛选模块 view 层接口,每个需要使用筛选功能的界面实现这个接口即可
 * <p>
 * Created by ZhangKe at 2017/7/30
 */
public interface IFilterView {

    /**
     * 设置界面筛选条件展示的列表
     *
     * @param list 筛选条件列表
     */
    void setProduceTypeList(List<ProduceTypeEntity> list);

    /**
     * 获取数据失败时回调的方法,界面上可以把错误信息展示出来
     *
     * @param code 错误码
     * @param msg  错误描述
     */
    void getFilterDataError(int code, String msg);
}

IFilterView 中只有一个方法,用于将获取到的数据更新到 View 层,需要使用筛选功能的地方实现这个功能即可:

package com.zhangke.androidmvp.Produce;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import com.zhangke.androidmvp.Filter.presenter.FilterPresenterImpl;
import com.zhangke.androidmvp.Filter.presenter.IFilterPresenter;
import com.zhangke.androidmvp.Filter.view.IFilterView;
import com.zhangke.androidmvp.Filter.entity.ProduceTypeEntity;
import com.zhangke.androidmvp.R;

import java.util.List;

/**
 * Created by ZhangKe at 2017/7/30
 */
public class ProduceShowActivity extends AppCompatActivity implements IFilterView{

    private IFilterPresenter filterPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_produce_show);

        filterPresenter = new FilterPresenterImpl(this);
        filterPresenter.getProduceTypeList();
    }

    @Override
    public void setProduceTypeList(List<ProduceTypeEntity> list) {
        //TODO 设置界面筛选条件展示的列表,比如可以弹出一个对话框或者其他
    }

    @Override
    public void getFilterDataError(int code, String msg) {
        //TODO 获取数据出错时向用户展示错误信息。
    }
}

ProduceShowActivity 实现了筛选模块的 IFilterView 接口之后便可以轻松的使用筛选功能,在其他需要使用筛选功能的地方都只要实现这个接口就可以了。
具体代码我已经放在 GitHub 上了,点此查看


以上就是我在小型项目中使用 MVP 的总结,主要思想就是: 将项目中常用的功能提取出来封装成一个 MVP 模块,这个模块完全由 MVP 来实现,其他地方不考虑。每个 MVP 模块专注自己的职能,遵守单一职责原则。在每个需要使用这个功能的地方实现对应的接口即可。


查看原文


END

猜你喜欢

转载自blog.csdn.net/u013872857/article/details/76360126