MVP入门实践
说到MVP肯定要先说下MVC,想必大家对android的MVC都有很深的了解。
View:布局文件,用于界面显示
Model:业务逻辑和实体模型
Controllor:对应于Activity,用于数据和界面的交互显示
由上图可以看出,View与数据的关系错综复杂,即activity不仅要负责数据的加工还要负责对数据的显示工作。一旦业务逻辑复杂,代码的可读性会大大的下降。
MVP设计思想与MVC有很大的不同,它将数据加工和界面交互的工作分开来做,即增加Presenter 负责完成View于Model间的交互。
这样一来,activity的代码量就会打打的下降。
接下来我们用一个简单的Demo来说明下:
下载Demo
下面就获取图片列表并显示在RecyclerView为例进行说明。
图片api使用的是新浪看见列表数据(声明:数据api仅用于学习交流)
api地址
请求使用GET方式,大家可以根据需要更改里面的参数,如page和num等
该api返回数据的格式为get_witness_list(json),所以不能直接转换为对象,我们只需要去除()内的json数据即可,具体做法不再赘述,下面来具体实现。
1.domain实体类
有了api和返回的数据我们可以很快的建立其对应的实体类,android studio用户推荐使用GsonFormat。由于实体类的参数比较多,这里不再贴出,有兴趣的可以查看Demo
2.model数据层
ImageLsitModel,调用实现里面的接口回调,并且传入页码参数。
[代码]java代码:
?
1 2 3 | public interface ImageListModel {
void getImageNewList(int page,ImageListModelImpl.OnImageNewLoadListenter listenter);
}
|
ImageListModelImpl,实现ImageLsitModel,并且声明接口OnImageNewLoadListenter
当成时返回 image对象(就是是一个list),失败时返回错误的原因。
[代码]java代码:
?
1 2 3 4 5 6 | public interface OnLoadImageListener {
void onSuccess(HenuImage image);
void OnFaild(String str);
}
|
在实现ImageListModel的方法中完成数据的获取,你可以使用自己认为比较合理的方式来实现,如RxJava+Retrofit,为了方便大家理解mvp我们直接使用okhttp来实现。
[代码]java代码:
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package com.flyou.seen.flyouseen.ImageList.model;
import com.google.gson.Gson;
import com.flyou.seen.flyouseen.ImageList.domain.ImageNews;
import com.flyou.seen.flyouseen.comm.APi;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;
import java.util.List;
import okhttp3.Call;
/**
* ============================================================
* 项目名称:HotWXReading
* 包名称:com.liuyajuan.login.hotwxreading.ImageList.model
* 文件名:ImageListModelImpl
* 类描述:
* 创建人:flyou
* 邮箱:fangjaylong@gmail.com
* 创建时间:2016/3/15 15:36
* 修改备注:
* 版本:@version V1.0
* ============================================================
**/
public class ImageListModelImpl implements ImageListModel {
@Override
public void getImageNewList(int page, final OnImageNewLoadListenter listenter) {
OkHttpUtils
.get()
.url(APi.IMAGE_NEW_LIST_URL + "page=" + page)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e) {
listenter.onFailed(e.getMessage(), e);
}
@Override
public void onResponse(String response) {
try {
String json = response.split("\\(")[1].split("\\)")[0];
ImageNews imageNews = new Gson().fromJson(json, ImageNews.class);
listenter.onSuccess(imageNews.getData());
}
catch (Exception e){
}
}
});
}
public interface OnImageNewLoadListenter {
void onSuccess(List<imagenews.dataentity> imageNews);
void onFailed(String msg, Exception e);
}
}</imagenews.dataentity>
|
3.View 界面展示层
ImageNewsView,主要提供界面交互需要的接口,一般为:
showLoading();显示进入条等加载界面
hideLoading();隐藏进度条等
showloadFailed();显示加载错误界面
getImageNew(object obj)获取数据并显示
这次Demo的View如下:
[代码]java代码:
?
1 2 3 4 5 6 | public interface HenuImageView {
void showLoading();
void hideLoading();
void GetImage(HenuImage henuImage);
void showLoadFaild(String str);
}
|
4.Presenter层,负责View和Model的交互和调度
ImgaeNewPresenter
[代码]java代码:
?
1 2 3 | public interface ImgaeNewPresenter {
void getImageList(int page);
}
|
ImageNewPresenterImpl
实现ImgaeNewPresenter和ImageListModelImpl.OnImageNewLoadListenter,在构造方法中完成View(activity实现) 和Model的初始化。
在getImageList()中loadingView可见,并且执行Modele层的数据获取操作
在onSuccess()中将loadingVeiw隐藏,并且将获取到的数据回调给view的实现类。
在onFailed()中将loadingVeiw隐藏,并且msg传给view的实现类。
[代码]java代码:
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class ImageNewPresenterImpl implements ImgaeNewPresenter, ImageListModelImpl.OnImageNewLoadListenter {
private ImageNewsView mImageNews;
private ImageListModelImpl mImageListModel;
public ImageNewPresenterImpl(ImageNewsView imageNews) {
this.mImageListModel = new ImageListModelImpl();
this.mImageNews = imageNews;
}
@Override
public void getImageList(int page) {
mImageNews.showLoading();
mImageListModel.getImageNewList(page, this);
}
@Override
public void onSuccess(List<imagenews.dataentity> imageNews) {
mImageNews.hideLoading();
mImageNews.addImage(imageNews);
}
@Override
public void onFailed(String msg, Exception e) {
mImageNews.hideLoading();
mImageNews.shwoLoadFaild(msg);
}
}</imagenews.dataentity>
|
5.Activity 界面展示
实现View层的接口,初始化persenter,调用persenterimpl的方法完成数据的获取。
在activity中:
[代码]java代码:
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | private ImgaeNewPresenter mImageNewPresenter;
public class MainActivity extends BaseActivity implements ImageNewsView{
@Override
onceate(){
初始化presenter
mImageNewPresenter = new ImageNewPresenterImpl(this);
mImageNewPresenter.getImageList(currentPage);
}
@Override
public void showLoading() {
// 显示加载界面
loadingView.setVisibility(View.VISIBLE);
}
@Override
public void addImage(List<imagenews.dataentity> imageNewList) {
// 界面展示
}
}
@Override
public void hideLoading() {
// 隐藏加载界面
}
@Override
public void shwoLoadFaild() {
// 显示获取数据错误界面
}
}</imagenews.dataentity>
|
这样一个简单的mvp功能就实现,数据层和View层完全分开了,这样在进行单元测试时就很方便了。
总结:mvp实际上就是将以前activity中复杂的数据获取和传递的过程抽离了出来,让Model来完成,persenter负责view和model的交互和数据的传递,将数据和视图分割开来,互不干扰,是项目的结构更加的清晰。
原文链接:http://www.apkbus.com/blog-705730-60610.html
打开App,阅读手记