您的位置:首页 > 理论基础 > 计算机网络

使用Retrofit+RxJava搭建简单的MVP网络请求框架

2017-12-26 15:09 991 查看
首先感谢蛇发女妖,偶尔在简书翻到这篇文章,很多地方都是借鉴这位的思想

另外感谢Season_zlc,大神的水管图很传神,刚接触RxJava的同学可以看看,撸完差不多也可以跟我一样简单使用了

老生常谈先介绍下MVC和MVP,先整张图



MVC:Android其实本身就是MVC模式,实现了视图于代码分离,视图是用XML画出来的,然后在Activity实现各种功能,作为一个开发者这是最简单的实现模式,除了视图外,各种封装model内的数据逻辑,以至于往往写了一个万能的Activity,,,

MVP:MVP是MVC的延伸,现在越来越多的开发者使用MVP框架,自然有他的优势,主要优势就体现在View和Model完全分离,即使我们修改了Model也不影响View的展现,View和Model所有的交互都有Presenter完成,View不参与交互,只注重视图及功能的实现

实现MVP步骤(个人感觉):

第一步Model,先构建数据层

第二步View,在实现视图层

第三步Presenter,最后使用Presenter进行交互

先看下我这个简单的MVP架构



我们就以上述步骤进行:

构建Model

Model就是数据模型,既然是数据模型那么就应该有数据,怎么获取数据呢,这就需要用到网络请求了,所以我们先写个简单的网络请求框架

网络请求我用的是Retrofit,在使用Retrofit之前先把依赖加上去

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'io.reactivex:rxandroid:1.2.0'


网络这块分了两部分写,一个是类一个是接口,接口(NetWorkRequestService)方面就十分简单了,主要就是实现接口访问网络,官方写法没什么改变,主要就是加了rxjava,只是把Call换成了Observable这里我请求的是豆瓣电影Top250

public interface NetWorkRequestService {
@GET("movie/top250")
Observable<MovieInfo> getMovie(@Query("start") int start, @Query("count") int count);
}


我们再看类(NetWorkHelper),这里主要增加了一个是静态实例,主要用于Model使用

private Retrofit mRetrofit;

private String BASEURL = "https://api.douban.com/v2/";

private static NetWorkHelper netWorkHelperInstance = null;
//实例用于Model调用
public static NetWorkHelper getInstance() {
if (netWorkHelperInstance == null) {
netWorkHelperInstance = new NetWorkHelper();
}
return netWorkHelperInstance;
}
//构造器
public NetWorkHelper() {
initRetrofit();
}

//Retrofit设置
private Retrofit initRetrofit() {
mRetrofit = new Retrofit.Builder()
.baseUrl(BASEURL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
return mRetrofit;
}

//将方法抽离,避免代码冗余
public NetWorkRequestService getSersver() {
return mRetrofit.create(NetWorkRequestService.class);
}


然后写Model,Model主要是调用网络请求数据,实现代码如下

NetWorkRequestService netWorkRequestService;
//获取netWorkRequestService
public MovieModel() {
netWorkRequestService = NetWorkHelper.getInstance().getSersver();
}
//这里写的是固定返回5条数据
public Observable<MovieInfo> getRequestMovieData() {
return netWorkRequestService.getMovie(0,5);
}


然后写View,View我也分成了两个,一个是父View,一个是具体实现的View

首先先看下父View,这里主要展示了三个状态,分别为请求中,成功,失败

/**
* 请求中.....
*/
void requestIng(String string);

/**
* 请求成功
*
* @param data
*/
void requestSuccess(T data);

/**
* 请求失败(非网络问题,一般为后台返回失败信息)
*
* @param errorMessage
*/
void requestError(String errorMessage);


然后MovieView继承父View重写方法,代码如下

@Override
void requestSuccess(Object data);

@Override
void requestIng(String string);

@Override
void requestError(String errorMessage);


重点看Presenter,跟View一样,我将Presenter也写了一个父Presenter,最好是按照Activity的生命周期来,这样便于我们更好的管理,我这里为了方便只写了三个方法

void onCreat();

void onStart(BaseView view);

void onStop();


具体实现代码,继承父Presenter重写父类方法,然后获取Model和View,然后构建桥梁,使用Model获取数据,然后将数据分状态给View

MovieModel movieModel;
MovieView movieView;
MovieInfo mMovieInfo;
//用于解绑
CompositeSubscription mCompositeSubscription;
Context mContext;

public MoviePresenter(Context context) {
this.mContext = context;
}

@Override
public void onCreat() {
//初始化
mMovieInfo = new MovieInfo();
movieModel = new MovieModel();
mCompositeSubscription = new CompositeSubscription();
}

@Override
public void onStart(BaseView view) {
//初始化View
movieView = (MovieView) view;
}

@Override
public void onStop() {
//解绑
if (mCompositeSubscription.hasSubscriptions()) {
mCompositeSubscription.unsubscribe();
}
}

public void setRequestData() {
//数据请求中
movieView.requestIng("请求中");
mCompositeSubscription.add(movieModel.getRequestMovieData()
.subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<MovieInfo>() {
@Override
public void onCompleted() {
//因为没找到code值所以就直接写了
if (mMovieInfo != null) {
//数据正确时,返回数据如code等于200
movieView.requestSuccess(mMovieInfo);
} else {
//error包括很多种,如code值非正确时返回的错误信息
movieView.requestError("数据有误");
}
}

@Override
public void onError(Throwable e) {
movieView.requestError(e.toString());
}

@Override
public void onNext(MovieInfo movieInfo) {
mMovieInfo = movieInfo;
}
}));
}


Presenter完成后工作几乎就完成了,只有在Activity中调用了,调用Presenter方法并回调View方法,具体实现代码如下:

private TextView mbtn;
MoviePresenter moviePresenter;
MovieInfo movieInfo;

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

private void init() {
movieInfo = new MovieInfo();
moviePresenter = new MoviePresenter(this);
mbtn = findViewById(R.id.btn);
moviePresenter.onCreat();
mbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
moviePresenter.setRequestData();
}
});
}

@Override
protected void onStart() {
super.onStart();
moviePresenter.onStart(this);
}

@Override
public void requestSuccess(Object data) {
movieInfo = (MovieInfo) data;
mbtn.setText(movieInfo.getTitle());
}

@Override
public void requestIng(String string) {
mbtn.setText(string);
}

@Override
public void requestError(String errorMessage) {
mbtn.setText(errorMessage);
}

@Override
protected void onDestroy() {
super.onDestroy();
moviePresenter.onStop();
}


效果如下图



下载地址:

CSDN下载地址

GitHub地址

最后再次感谢蛇发女妖Season_zlc两位大神
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: