文章插图
上面的代码,其实就是 MVC 架构的写法,把 Model(网页数据)、Presenter(数据处理)、View(activity)三层写在了一起,虽然没什么问题,但我们看看 MainActivity 中的代码比较杂乱,在业务代码比较多的情况下,MainActivity 更加的沉重,不利于维护与业务升级 。
MVP 实战那么我们下面就要将这个类中的代码改写为 MVP 的写法,回顾上面提及的 MVP 架构的思想,它是将 View 层与 Model 层彻底隔离,意味着 View 和 Model 都不再持对方的引用,它们通过一个第三者 Presenter 来代理事物的传递,所以 Presenter 层会持有 Model 与 View 层的引用,这是第一步 。
第二步,是将它们之间的联系抽象出来,以接口的方式相互调用,所以 Model 、View、Presenter 各自拥有自己的接口和抽象方法,所以这就会无形的多出了三个接口类,这也就是 MVP 的缺点之一 。所以,为了较少的创建接口类,我们就给这三层接口定义了一个契约接口,把它们更加紧密的结合在一起,方法查看,例如代码这样写:
(1)契约类:
package com.test.mvp.mvpdemo.mvp.v1; import okhttp3.Callback; /** * 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法 */public interface MainContract { interface IMainModel { void requestBaidu(Callback callback); }interface IMainView { void showDialog();void succes(String content); }interface IMainPresenter { void handlerData(); }}然后,再将之前的一个单独的 MainActivity 分包,分别创建 Model 层实现类、Presenter 层实现类、MainActivity 就相当于View 层,这样一来架构就更加清晰明了:
文章插图
接着,分别给这三层实现我们刚刚写的 MainContract 中相对应的接口,我们先来看看 Model 层,它就主要负责网络请求,也就是我们的 OKHttp 请求到百度首页的一个操作,很简单的代码 。
(2)Model 层:
package com.test.mvp.mvpdemo.mvp.v1.model; import com.test.mvp.mvpdemo.mvp.v1.MainContract; import okhttp3.Callback;import okhttp3.OkHttpClient;import okhttp3.Request; /** * model 层,请求网络或数据库,提供数据源(原始数据) */public class DataModel implements MainContract.IMainModel {@Override public void requestBaidu(Callback callback) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://www.baidu.com/") .build(); client.newCall(request).enqueue(callback); }}这里需要传入一个 OKHttp 的 Callback,由于不能在 Model 层中处理业务数据,所以我们让它自己回调给 Presenter 层来处理,保证数据的原始状态 。
(3)Presenter 层:
然后是 Presenter 层,它是处理业务逻辑和业务数据的,所以必须持有 Model 的引用,同时要将处理完的数据交给 View 层用于显示,也必须持有 View 的引用,那么,一开始我们就要把这两层给实例化,具体看下面的代码:
package com.test.mvp.mvpdemo.mvp.v1.presenter; import com.test.mvp.mvpdemo.mvp.v1.MainContract;import com.test.mvp.mvpdemo.mvp.v1.model.DataModel; import JAVA.io.IOException; import okhttp3.Call;import okhttp3.Callback;import okhttp3.Response; /** * presenter 层,承担业务逻辑处理,数据源处理等 */public class MainPresenter implements MainContract.IMainPresenter {private MainContract.IMainModel mModel; private MainContract.IMainView mView;public MainPresenter(MainContract.IMainView view) { this.mView = view; mModel = new DataModel(); }@Override public void handlerData() { if (mView != null) { mView.showDialog(); } /** * 发起请求,获得回调数据 */ mModel.requestBaidu(new Callback() { @Override public void onFailure(Call call, IOException e) { }@Override public void onResponse(Call call, Response response) throws IOException { String content = response.body().string(); if (mView != null) { mView.succes(content); } } }); }}这里的处理数据我就不做说明了,注意一点,这里是请求网络数据会有延时,我们 Presenter 层持有了 View 层的引用,也就是 Activity 的引用,在网络堵塞的情况下,用户在打开 Activity 又马上给关闭了,这时 View 相当于被摧毁了,如果不进行判断 View 引用是否为空,当数据在延迟几秒后返回时,就会造成空指针异常,所以每次都要进行判断才合理 。
【Android MVP 架构介绍与使用入门】最后,在 Presenter 层处理完了数据,就要将数据传达给 View 层显示,所以要调用 View 接口的抽象方法,把数据参数传递过去,那么 View 在收到数据后,不需要多余的逻辑操作,直接显示就好了 。那么 View(MainActivity)的代码应该做如下修改:
推荐阅读
- 阿里架构总监13张PPT一次讲透中台架构
- B/S架构web请求过程详解
- Android打包之多版本、多环境、多渠道
- 大型网站架构负载均衡详解
- 一文搞懂MySQL的Join,聊一聊秒杀架构设计
- InputManagerService 十分钟让你了解Android触摸事件原理
- 用电脑控制Android手机,玩游戏看视频都可以,还支持无线连接
- JD架构师分享:微服务架构到底是什么东西
- Android:手把手带你清晰梳理自定义View工作全流程
- 现在程序员最火的微服务架构与SpringCloud,你真的弄清楚了吗?