Android 搭建MVP+Retrofit+RxJava网络请
上一篇中简单介绍了mvp的概念和retrofit的基本使用,本篇主要是将rxjava和retrofit结合起来使用,并搭建mvp+rxajva+retrofit的demo;没有rxjava和retrofit基础的,建议先去看上一篇:
Android 搭建MVP+Retrofit+RxJava网络请求框架(一)
下面我们来看一下RxJava和retrofit的结合使用,为了使Rxjava与retrofit结合,我们需要在Retrofit对象建立的时候添加一句代码:
addCallAdapterFactory(RxJava2CallAdapterFactory.create())
当然你还需要在build.gradle文件中添加如下依赖:
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
本篇中所用的是rxjava2,完整的代码如下:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.douban.com/v2/")
.addConverterFactory(GsonConverterFactory.create(new
GsonBuilder().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持RxJava
.build();
然后我们还需要修改RetrofitService 中的代码:
public interface RetrofitService {
@GET("book/search")
Observable<Book> getSearchBook(@Query("q") String name,
@Query("tag") String tag, @Query("start") int start,
@Query("count") int count);
可以看到,在原来的RetrofitService 中我们把getSearchBook方法返回的类型Call改为了Observable,也就是被观察者。其他都没变。然后就是创建RetrofitService 实体类:
RetrofitService service = retrofit.create(RetrofitService.class);
和上面一样,创建完RetrofitService ,就可以调用里面的方法了:
Observable<Book> observable = service.getSearchBook("人间失格", null, 0, 1);
其实这一步,就是创建了一个rxjava中observable,即被观察者,有了被观察者,就需要一个观察者,且订阅它:
observable.subscribeOn(Schedulers.io())//请求数据的事件发生在io线程
.observeOn(AndroidSchedulers.mainThread())//请求完成后在主线程更显UI
.subscribe(new DisposableObserver<Book>() {//订阅
@Override
public void onComplete() {
//所有事件都完成,可以做些操作。。。
}
@Override
public void onError(Throwable e) {
e.printStackTrace(); //请求过程中发生错误
}
@Override
public void onNext(Book book) {//这里的book就是我们请求接口返回的实体类
}
}
在上面中我们可以看到,事件的消费在Android主线程,所以我们还要在build.gradle中添加如下依赖:
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
这样我们就引入了RxAndroid,RxAndroid其实就是对RxJava的扩展。比如上面这个Android主线程在RxJava中就没有,因此要使用的话就必须得引用RxAndroid。
实践
接下来我们就看看,在一个项目中上面三者是如何配合的。我们打开Android Studio,新建一个项目取名为MVPSample。这个demo的功能也很简单,就是点击按钮调用上面的那个测试接口,将请求下来书的信息显示在屏幕上。首先我们来看一下这个工程的目录结构:
![](https://img.haomeiwen.com/i6983034/9dfed4eee58335a5.png)
我们可以看到,在项目的包名下,我们建了主要的文件夹:bean、data、presenter,ui;分别对应不同的功能。其中app文件夹中可以建一个Application类,用于设置应用全局的一些属性,这里为了使项目更加简单就没有添加;然后,我们再来看看ui文件夹下,这个文件夹下主要放一些关于界面的东西。在里面我们又建了三个文件夹:activity、adapter、fragment,我想看名字你就清楚里面要放什么了。RetrofitHelper和APiService。RetrofitHelper主要用于Retrofit的初始化:
public class RetrofitHelper {
private Context mCntext;
OkHttpClient client = new OkHttpClient();
GsonConverterFactory factory = GsonConverterFactory.create(new GsonBuilder().create());
private static RetrofitHelper instance = null;
private Retrofit mRetrofit = null;
public static RetrofitHelper getInstance(Context context){
if (instance == null){
instance = new RetrofitHelper(context);
}
return instance;
}
private RetrofitHelper(Context mContext){
mCntext = mContext;
init();
}
private void init() {
resetApp();
}
private void resetApp() {
mRetrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.client(client)
.addConverterFactory(factory)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
public ApiService getServer(){
return mRetrofit.create(ApiService.class);
}
}
代码并不复杂,其中resetApp方法,就是前面介绍的Retrofit的创建,getServer方法就是为了获取ApiService接口类的实例化。然后定义了一个静态方法getInstance用于获取自身RetrofitHelper的实例化,并且只会实例化一次。
在正式的项目中model,view,presenter都需要根据需求创建对应的BaseView,BaseModel,BasePresenter;当前demo中只是简单创建,后再后续封装中继续完善框架。
先创建一个BookInfoContract
public interface BookInfoContract {
interface IView extends BaseView {
void showResult(String msg);
// void onRequestPermissionSuccess();
//
// void onRequestPermissionSError();
}
interface IBookModel {
Observable<Book> getBookMsg(String name,String tag,int start,int count);
}
}
这是采用google官方demo的写法,将相关的view和model接口写到一个协议接口类中。方便查找和管理,每一个view,model,presenter都有对应的接口类相对应,这种写法虽然类增加了,但是便于解耦,改动和维护方便;
具体实现步骤如下:
- 创建BookInfoModel,实现接口,并重写获取数据的方法
public class BookInfoModel implements BookInfoContract.IBookModel {
private ApiService mApiService;
public BookInfoModel(ApiService mApiService) {
this.mApiService = mApiService;
}
@Override
public Observable<Book> getBookMsg(String name, String tag, int start, int count) {
return mApiService.getSearchBooks(name, tag, start, count);
}
}
2.创建presenter,通过构造传入需要关联的view,并初始化model;在getMsg()方法中,通过model中
getBookMsg()方法返回的被观察者进入线程切换和事件订阅;在订阅回调中,调用view的方法对请求的结果进行处理;一般presenter持有view的引用,增加了耦合性,后面会进行优化处理
public class BookPresenter {
private BookInfoContract.IView mView;
private BookInfoModel bookInfoModel;
private Book mBook;
public BookPresenter(BookInfoContract.IView mView) {
this.mView = mView;
bookInfoModel = new BookInfoModel(RetrofitHelper.getInstance((Context) mView).getServer());
}
//获取数据
public void getMsg(String name, String tag, int start, int count) {
bookInfoModel.getBookMsg(name, tag, start, count)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Book>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Book value) {
mBook = value;
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
mView.showError("请求失败");
}
@Override
public void onComplete() {
if (mView != null) {
mView.showResult(mBook.toString());
}
}
});
}
}
3.在mainActivity中实现接口 BookInfoContract.IView;通过注解初始化控件(在onDestroy中进行接触注解)并获取初始化presenter,在控件监听事件中。调用presenter的方法获取数据;
经过以上几步基本完成了mvp+rxjava+retrofit的框架搭建
项目地址:https://github.com/cruiseliang/MvpSample