适用于小型项目的 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:
如上图所示,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 架构的思想之一就是代码重用,我们把重复性代码提取出来正好也实现了这个想法。接着上面的需求,我们把项目改成如下模式:
修改之后的包结构新增了一个 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
上一篇: JS+Struts2多文件上传实例详解
下一篇: Python中几种导入模块的方式总结