顺风笑嘻嘻,逆风mmp!
接着上一篇,上一篇其实隐含着一个比较大的问题,那就是MainActivity中,逻辑代码太多带来的直接问题就是看起来特别臃肿,如果后面继续添加功能,修改起来也麻烦,也就是扩展性也比较差。Activity大兄弟很气啊,mmp凭啥什么事情都交给我干,所以需要引入其他兄弟来分担下Activity的任务咯。
在Android远古时代,大家写代码都是直接在Activity里写。
中古时代,引入了M层,然后分为Model层和Control层。
现代的MVP模式(本篇不谈MVVM),又细化了引入了P层,Presenter层。mvp模式在某种程度来说跟现代的企业模式很像,那就是专业的事情交给专业的“人”来做。比如说View层只做展示操作(什么叫展示操作,即和xml中控件相关的操作,比如text.setText等)、Model层做数据处理操作、Presenter层做逻辑处理操作以及连接V和P,而我们把Activity当成View层。这样的好处是:
在我的理解中引入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层主要是对数据的一些展示,代码如下:
/**
*
* 作者 : 肖坤
* 时间 : 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);
}
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源码解析