MVP 入门实践 - 分享自@开发者头条
说到MVP肯定要先说下MVC,想必大家对android的MVC都有很深的了解。
View:布局文件,用于界面显示
Model:业务逻辑和实体模型
Controllor:对应于Activity,用于数据和界面的交互显示
由上图可以看出,View与数据的关系错综复杂,即activity不仅要负责数据的加工还要负责对数据的显示工作。一旦业务逻辑复杂,代码的可读性会大大的下降。
MVP设计思想与MVC有很大的不同,它将数据加工和界面交互的工作分开来做,即增加Presenter 负责完成View于Model间的交互。
这样一来,activity的代码量就会打打的下降。
接下来我们用一个简单的Demo来说明下:
下载Demo
下面就获取图片列表并显示在RecyclerView为例进行说明。
图片api使用的是新浪看见列表数据(声明:数据api仅用于学习交流)
请求使用GET方式,大家可以根据需要更改里面的参数,如page和num等
该api返回数据的格式为get_witness_list(json),所以不能直接转换为对象,我们只需要去除()内的json数据即可,具体做法不再赘述,下面来具体实现。
1.domain实体类
有了api和返回的数据我们可以很快的建立其对应的实体类,android studio用户推荐使用GsonFormat。由于实体类的参数比较多,这里不再贴出,有兴趣的可以查看Demo
2.model数据层
ImageLsitModel,调用实现里面的接口回调,并且传入页码参数。
public interface ImageListModel {
void getImageNewList(int page,ImageListModelImpl.OnImageNewLoadListenter listenter);
}
ImageListModelImpl,实现ImageLsitModel,并且声明接口OnImageNewLoadListenter
当成时返回 image对象(就是是一个list),失败时返回错误的原因。
public interface OnLoadImageListener {
void onSuccess(HenuImage image);
void OnFaild(String str);
}
在实现ImageListModel的方法中完成数据的获取,你可以使用自己认为比较合理的方式来实现,如RxJava+Retrofit,为了方便大家理解mvp我们直接使用okhttp来实现。
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);
}
}
3.View 界面展示层
ImageNewsView,主要提供界面交互需要的接口,一般为:
showLoading();显示进入条等加载界面
hideLoading();隐藏进度条等
showloadFailed();显示加载错误界面
getImageNew(object obj)获取数据并显示
这次Demo的View如下:
public interface HenuImageView {
void showLoading();
void hideLoading();
void GetImage(HenuImage henuImage);
void showLoadFaild(String str);
}
4.Presenter层,负责View和Model的交互和调度
ImgaeNewPresenter
public interface ImgaeNewPresenter {
void getImageList(int page);
}
ImageNewPresenterImpl
实现ImgaeNewPresenter和ImageListModelImpl.OnImageNewLoadListenter,在构造方法中完成View(activity实现) 和Model的初始化。
在getImageList()中loadingView可见,并且执行Modele层的数据获取操作
在onSuccess()中将loadingVeiw隐藏,并且将获取到的数据回调给view的实现类。
在onFailed()中将loadingVeiw隐藏,并且msg传给view的实现类。
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);
}
}
5.Activity 界面展示
实现View层的接口,初始化persenter,调用persenterimpl的方法完成数据的获取。
在activity中:
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() {
//显示获取数据错误界面
}
}
这样一个简单的mvp功能就实现,数据层和View层完全分开了,这样在进行单元测试时就很方便了。
总结:mvp实际上就是将以前activity中复杂的数据获取和传递的过程抽离了出来,让Model来完成,persenter负责view和model的交互和数据的传递,将数据和视图分割开来,互不干扰,是项目的结构更加的清晰。
有什么我写的不妥的地方,欢迎大家指正!
查看原文