App架构设计实战一:初步引入MVP

App架构设计实战一:初步引入MVP

顺风笑嘻嘻,逆风mmp!

接着上一篇,上一篇其实隐含着一个比较大的问题,那就是MainActivity中,逻辑代码太多带来的直接问题就是看起来特别臃肿,如果后面继续添加功能,修改起来也麻烦,也就是扩展性也比较差。Activity大兄弟很气啊,mmp凭啥什么事情都交给我干,所以需要引入其他兄弟来分担下Activity的任务咯。

Android架构进化史

App架构设计实战一:初步引入MVP_第1张图片

在Android远古时代,大家写代码都是直接在Activity里写。

中古时代,引入了M层,然后分为Model层和Control层。

现代的MVP模式(本篇不谈MVVM),又细化了引入了P层,Presenter层。mvp模式在某种程度来说跟现代的企业模式很像,那就是专业的事情交给专业的“人”来做。比如说View层只做展示操作(什么叫展示操作,即和xml中控件相关的操作,比如text.setText等)、Model层做数据处理操作、Presenter层做逻辑处理操作以及连接V和P,而我们把Activity当成View层。这样的好处是:

  • 代码层次比较分明;
  • 单元测试更加简单(相当于没有,因为我这里根本就不做单元测试);
  • 分解了原Activity的功能,轻量化Activity;
  • 相对更解耦,即后期扩展比较容易。

引入MVP

引入M

在我的理解中引入MVP层,一开始是从Model层开始引入的。可以这么写:

/**
 * 
 *     作者   : 肖坤
 *     时间   : 2018/04/23
 *     描述   : m层,里面主要提供对数据的操作方法
 *     版本   : 1.0
 * 
*/
public class MainModel { private ApiService apiService = RetrofitHelper.createService(ApiService.class, false); //获取"tools/mockapi/440/yx0419"接口数据 public Observable getHttpData1() { return apiService.getHttpData1() .map(new HttpResultFunc()) .compose(RxSchedulers.io_main()); } //获取"tools/mockapi/440/yx04191"接口数据 public Observable getHttpData2() { return apiService.getHttpData2() .map(new HttpResultFunc()) .compose(RxSchedulers.io_main()); } //获取"tools/mockapi/440/yx04192"接口数据 public Observable getHttpData3() { return apiService.getHttpData3() .map(new HttpResultFunc()) .compose(RxSchedulers.io_main()); } //获取"tools/mockapi/440/token_expired"接口数据 public Observable getExpiredHttp() { return apiService.getExpiredHttp() .map(new HttpResultFunc()) .compose(RxSchedulers.io_main()); } //下载 public Observable downLoadFile(String url, DownloadEntity downloadEntity) { ApiService apiService = RetrofitHelper.createService(ApiService.class, RetrofitHelper.getDownloadRetrofit(downloadEntity)); return apiService.downLoadFile(url).subscribeOn(Schedulers.io()); } }

m层主要是对数据的一些处理,比较简单。

引入V和P

V层主要是对数据的一些展示,代码如下:

/**
 * 
 *     作者   : 肖坤
 *     时间   : 2018/04/23
 *     描述   : V层
 *     版本   : 1.0
 * 
*/
public interface MainView { void getHttp1Suc(ResEntity1.DataBean dataBean); void getHttp1Failed(String errorMsg); void getHttp2Suc(ResEntity1.DataBean dataBean); void getHttp2Failed(String errorMsg); void getHttp3Suc(ResEntity1.DataBean dataBean); void getHttp3Failed(String errorMsg); void getExpiredSuc(ResEntity1.DataBean dataBean); void getExpiredFailed(String errorMsg); void downloadDisposable(Disposable disposable); }

App架构设计实战一:初步引入MVP_第2张图片

P层除了包括逻辑的处理外,还有一个很重要的作用就是连接V和M。因为在MVP模式中Model层和View层是不直接接触的。所以P层的构造方法如下:

public MainPresenter(MainView view, RxManager rxManager)
{
    this.viewWeakRef = new WeakReference(view);
    this.rxManager = rxManager;
    mainModel = new MainModel();
}

因为MVP模式中V层一般都是Activity或者Fragment,属性系统有声明周期的组件,稍不注意就可能会引起内存泄漏(也就是内存没有及时回收),所以这里用一个弱引用来进行第一层规避。还有在这里初始化了Model。

P层代码整体如下:

/**
 * 
 *     作者   : 肖坤
 *     时间   : 2018/04/23
 *     描述   : P层 作用:连接V和M,逻辑操作处理
 *     版本   : 1.0
 * 
*/
public class MainPresenter { private WeakReference viewWeakRef; private RxManager rxManager; private MainModel mainModel; public MainPresenter(MainView view, RxManager rxManager) { this.viewWeakRef = new WeakReference(view); this.rxManager = rxManager; mainModel = new MainModel(); } public MainView getView() { return viewWeakRef.get(); } public void getHttp1() { mainModel.getHttpData1().subscribe(new BaseObserver(rxManager) { @Override protected void onErrorMsg(String msg) { getView().getHttp1Failed(msg); } @Override public void onNext(ResEntity1.DataBean dataBean) { getView().getHttp1Suc(dataBean); } }); } //省略中间很多代码 //暂停下载 public void pauseDownload(Disposable disposable, String fileName) { DownloadManager.pauseDownload(disposable, fileName); } //取消下载 public void cancelDownload(Disposable disposable, String fileName) { DownloadManager.cancelDownload(disposable, fileName); } //解绑view,并取消网络 public void detachView() { if (viewWeakRef != null) { viewWeakRef.clear(); viewWeakRef = null; } if (rxManager != null) { rxManager.clear(); } } }

我们在末尾有一个detachView方法,解绑view,这里做了第二层的内存泄漏的规避。这里的detachView一般在Activity中的onDestroy方法中调用:

@Override
protected void onDestroy()
{
    super.onDestroy();
    mainPresenter.detachView();
}

而Presenter的初始化一般都放在Activity的onCreate方法中:

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

    rxManager = new RxManager();
    mainPresenter = new MainPresenter(this, rxManager);
}

这样整体各司其职,就很舒服了。有没有懂的胸低!

后话

其实我们在项目中要灵活运用MVP模式。比如我认为在中小型应用中,可以一个模块用一个P和一个M,因为真的没有必要每一个页面都给造一个Presenter一个Model和一个View。当然哦,每个页面的View是要单独要的。但是Model和Presenter真的可以用一个模块分别提供一个。有没有懂得兄弟,不用我告诉你要干嘛吧?刷波6。

github:Demo

以上。

上篇博客:App网络请求实战三:下载文件以及断点续载
下篇博客:
App网络请求实战四:rxjava操作符flatMap使用以及rxjava源码解析

你可能感兴趣的:(Android实战开发)