博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于MVP分层架构在项目中的实际运用
阅读量:5782 次
发布时间:2019-06-18

本文共 5404 字,大约阅读时间需要 18 分钟。

关于MVP的基本知识网上已经有很多了,但是很多都只是Demo,毕竟Demo跟实际运用之间还有无数个Debug,其实一开始我也看了很多关于MVP的介绍,其中有谷歌官方的Demo,还有很多技术博客,那个时候就觉得自己知道什么是MVP了,后来真正在自己项目中运用的时候,才发现并不是那么简单,不过经过一番折腾,逐渐对MVP有了比较深层次的认识,所以今天记录分享一下。

MVP结构示意图

我自己画了一个关系图,也就是最简单的MVP结构示意图,我在这里并不会再解释什么是MVP,今天我想把所有的认知转化为代码,也就是图中的关系图,他们之间的关系我全部都是用Callback来进行联系的,也就是之前说的引用。

M层

  • 这里的M层不是传统意义上的Model,我更倾向于认为他是一个ModelManager,就是一个数据处理中心,可以处理网络数据,数据库,文件以及关于Android中的四大组件的交互包含BroadcastReceiver,Service中的,都可以集中在这里面处理,有很长一段时间对于M的认知都是觉得就是个实体类,那个时候还以为自己掌握地很透彻,最后发现自己理解的其实是不对的,MddelManager持有Presenter的引用,M处理完数据之后通过Callback回调Presenter,Presenter由于持有View的引用,所以可以回调View

V层

  • V就是指View(界面),往大了说是Activity或者Fragemnt,往小了说可以是一个Dialog、Toast或者Snakbar,具体就是直接跟用户进行打交道的,View会实现Callback接口,然后传递给Presenter,然后Presenter会去ModelManager进行交互,然后数据处理完成之后,会通过Callback回调回来,这样就完成了一个闭环

P层

  • P就是Presenter,主持人其实挺形象的,就起一个客串的作用,相当于一座桥,来连接Vie跟ModelManger,很多文章是把逻辑在Presenter中进行处理的,我觉得不是很好,我认为在Modelmanager里面处理比较好,这样解耦的更彻底,毕竟Presenter只是个中间的信使而已,不应该处理过多的逻辑。

关系搞清楚了,其实代码实现就比较简单

M层代码

public class MainManager {    private ViewCallBack mViewCallBack;    public MainManager(ViewCallBack viewCallBack) {        this.mViewCallBack = viewCallBack;    }    public void getData() {        mViewCallBack.refreshView(1, "数据");    }}复制代码

这里面只是写了一个模板,可能一个界面需要多种数据处理方式,那么就根据需求在重新定义几个方法即可

V层代码

public interface ViewCallBack
{ /** * @param code code:0:有数据,1:数据为空,2:加载失败 * @param data 定义好的数据类型 */ void refreshView(int code, V data);}复制代码

这里的V采取泛型的原因在于每个界面需要获取的数据不一样,所以用泛型加以区分,当一个界面需要获取的接口很多,或者得到的数据结果类型不太一致的时候,这里的泛型就需要用Object来指定,然后在refreshView中通过数据的类型来判断需要刷新的数据

P层代码

public class MainPresenter {    private ViewCallBack mViewCallBack;    private MainManager mMainManager;    public MainPresenter(ViewCallBack viewCallBack) {        this.mViewCallBack = viewCallBack;        mMainManager = new MainManager(mViewCallBack);    }    public void getData() {        mMainManager.getData();    }}复制代码

P层代码的方法跟Manager对应,然后处理M层跟V层的Callback即可,但是注意Presenter是一个对象,需要在界面销毁的时候置空,防止内存泄露

我在demo中只是简单写了一个改变Text的值,当然在Manager里面可以进行任何你想要的操作,因为是采用接口回调,运行一下看看效果

MVP效果图

持续封装

上面的只是一个Demo,下面进行封装抽取,方便集成到真正的项目中去

  1. M层封装
public abstract class BaseBeanManager {    protected ViewCallBack mViewCallBack;    protected HashMap
paramMap; public BaseBeanManager(ViewCallBack modelCallBack) { mViewCallBack = modelCallBack; } public abstract void getData();}复制代码
  1. V层封装
public abstract class BaseActivity
extends AppCompatActivity implements ViewCallBack
{ public T presenter;//泛型定义Presenter @TargetApi(Build.VERSION_CODES.M) @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(getLayoutId()); presenter = initPresenter(); initViews(); initListener(); } @Override protected void onResume() { super.onResume(); //初始化Presenter if (presenter == null) presenter = initPresenter(); //添加Callback presenter.add((ViewCallBack) this); } protected abstract int getLayoutId(); protected abstract void initViews(); protected abstract void initListener();//初始化监听事件 protected abstract T initPresenter();//初始化Presenter @Override protected void onDestroy() { super.onDestroy(); //生命周期结束时销毁callback,并置空presenter if (presenter != null){ presenter.remove(); presenter = null; } }}复制代码
  1. P层封装
public abstract class BasePresenter {    protected BaseBeanManager mBeanManager;//定义基类manager    protected HashMap
paramMap = new HashMap<>(); protected ViewCallBack mViewCallBack; public BasePresenter(ViewCallBack viewCallBack) { mViewCallBack = viewCallBack; } public void add(ViewCallBack viewCallBack) { this.mViewCallBack = viewCallBack; } public void remove() { this.mViewCallBack = null; } //默认的获取数据的方法 protected abstract void getData();}复制代码

使用

  1. M层
public class MainManager extends BaseBeanManager {    public MainManager(ViewCallBack modelCallBack) {        super(modelCallBack);    }    public void getData() {        mViewCallBack.refreshView(1, "MVP返回的数据");    }}复制代码

2.V层

public class MainActivity extends BaseActivity
implements ViewCallBack
{ private TextView tvDemo; private Button btnGet; @Override protected int getLayoutId() { return R.layout.activity_main; } @Override protected void initViews() { tvDemo = (TextView) findViewById(R.id.tv_demo); btnGet = (Button) findViewById(R.id.btn_get); } public void initListener() { btnGet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.getData(); } }); } @Override protected MainPresenter initPresenter() { return new MainPresenter(this); } @Override public void refreshView(int code, String data) { tvDemo.setText(data); }}复制代码
  1. P层
public class MainPresenter extends BasePresenter {    public MainPresenter(ViewCallBack viewCallBack) {        super(viewCallBack);    }    public void getData() {        mBeanManager = new MainManager(mViewCallBack);        mBeanManager.getData();    }}复制代码

本身是不想贴这么多代码的,但是只有对比才能发现,MVP由于解耦地比较彻底,所以满足单一职责原则,新增了很多类,封装之后,即使新建的类变多了,每个类都需要一个相应的Presenter,但是代码量很少,所以看起来逻辑比较清楚

这就是我的项目中正在使用的的MVP,刚开始从MVC转换过来的时候很不习惯,后来折腾了一阵子,发现其实挺好用的。

转载地址:http://odjyx.baihongyu.com/

你可能感兴趣的文章
自动化运维工具Ansible详细部署 - 人生理想在于坚持不懈 - 51CTO技术博客
查看>>
微信公众平台开发教程--方培工作室,PHP语言版本
查看>>
FastMM 定位内存泄露的代码位置
查看>>
Bootstrap系列 -- 41. 带表单的导航条
查看>>
EF和LINQ 调用存储过程
查看>>
App如何选择移动广告平台的开发者3 - 选择标准广告平台
查看>>
页面距离总结
查看>>
Linux主机在LNMP环境中同时运行多个PHP版本
查看>>
IOS NSNotification Center 通知中心的使用
查看>>
Device Tree(二):基本概念
查看>>
实现类似微信的延迟加载的Fragment——LazyFragment
查看>>
(转)在公司的局域网使用git或github 设置代理
查看>>
全才学霸是怎样管理时间的?
查看>>
高可用Hadoop平台-Oozie工作流
查看>>
.NET破解之太乐地图下载器【非暴破】
查看>>
mac 如何让文件隐藏
查看>>
Scala 深入浅出实战经典 第77讲:模式匹配下的提取器动手构造实战
查看>>
加密概述
查看>>
linux 下查看网速的方法 (不需要安装任何软件)
查看>>
systemtap 2.8 安装说明书
查看>>