欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-02-26 13:02:52
...

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:

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


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

具体实现

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

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


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

在小项目中使用 MVP

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

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


修改之后的包结构新增了一个 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