RxJava+MVP+Retrofit项目实战
始终认同“技术服务于业务”这句话,尽管我们项目还没有使用RxJava,但我们已经开始学习和准备使用RxJava重构项目,我想现在为时还不算晚吧!本项目将通过一个小案例来探究,在实战项目中使用RxJava、MVP架构、网络请求框架Retrofit。
0 提纲
1 模块介绍
1.1 RxJava模块
RxJava在Github上自我介绍到:一个在Java VM上使用可观测的序列来组成异步的、基于事件的程序的库。
RxJava扩展了观察者模式来支持数据和事件序列,添加操作允许你一起组成序列声明,当抽象出来像低线程同步问题,线程安全和并发数据结构。RxJava的特性:
- 零依赖
- 小于1M的jar包
- 支持java6以上和Android2.3以上
- 支持java8 lambda
- 支持预言包括:Scala、Groovy、Clojure和Kotlin
- 非强制性的并发源:线程、池、事件循环、fibers、actors等
- 同步或异步执行
- 参数化的并发虚拟时间和调度
在没有使用RxJava之前,我们写一个异步操作会这样:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public void getPersonInfoToShow(int id) {
mIShowPersonView.showLoading();
mIGetPerson.getPersonInfo(id, new onPersonInfoListener() {
public void getPersonInfoSuccess(final Person person) {
mHandler.post(new Runnable() {
public void run() {
mIShowPersonView.toNextActivity(person);
mIShowPersonView.dismissLoading();
}
});
}
public void getPersonInfoFailed() {
mHandler.post(new Runnable() {
public void run() {
mIShowPersonView.showFailedError();
mIShowPersonView.dismissLoading();
}
});
}
});
}
|
在使用了RxJava之后,不再受回调方法、匿名内部类的嵌套折腾了,简单的调用链就OK。
|
1
2
3
4
5
6
7
8
9
|
Observable<String> myObservable = Observable.create(
new Observable.OnSubscribe<String>() {
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello RxJava!");
sub.onCompleted();
}
}
);
|
Gradle依赖代码为:
|
1
2
|
compile 'io.reactivex:rxjava:x.y.z'
compile 'io.reactivex:rxandroid:1.0.1'
|
1.2 MVP模块

说到MVP架构总要跟MVC架构进行对比,尽管只差了一个字母而已。在传统的MVC架构中,View层是能够跟Model层直接进行沟通,而在MVP架构中View层与Model层要通过Presenter这个主持人来进行沟通,这样有利于模块解耦和对模块进行单元测试。在MVP架构中各个模块功能如下:
-
View层:View层是由对用户可见的Activity、Fragment、ViewGroup、View组成。通过实现抽象接口与Presenter层进行业务逻辑的交互
-
Presenter层:Presenter层是作为View层与Model层的“媒婆”存在
-
Model层:Model层主要进行数据管理,包含回调接口、接口实现类
项目的SimpleActivity.java就是MVP的简单使用,下面是简单MVP的UML类图。

1.3 Retrofit模块
Retrofit出自大厂Square,Square出了很多开源库,涵盖Android、iOS、Go、Java、Javascript、Ruby等编程语言,实在是强悍!而我们熟知的网络请求框架OkHttp也是同样出自Square。在自我介绍中,Retrofit号称:为Android和Java而生的类型安全的Http客户端。Retrofit有以下特性:
使用注解描述http请求:
- 支持url参数替换和查找
- 对象转换为请求体(可以包括:json、protocol buffers)
- 拆分的请求体和文件上传
- 支持五种内建注解:GET、PUT、POST、DELETE、HEAD
Gradle依赖代码为:
|
1
2
3
|
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
|
2 实战项目
本项目目录结构为:

2.1 将Http Api添加到一个java接口
|
1
2
3
4
5
6
|
public interface NewsService {
Observable<NewsBean> news(
@Query("rows") Integer rows
);
}
|
2.2 生成NewsService接口的实现
|
1
2
3
4
|
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()).baseUrl(ApiConstant.HOST_API).build();
NewsService service = retrofit.create(NewsService.class);
|
2.3 使用RxJava获取数据并显示
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
service.news(currentPage)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.doOnNext(new Action1<NewsBean>() {
public void call(NewsBean newsBean) {
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<NewsBean>() {
public void onCompleted() {
idSwipeRefreshLayout.setRefreshing(false);
}
public void onError(Throwable e) {
idSwipeRefreshLayout.setRefreshing(false);
}
public void onNext(NewsBean newsBean) {
if (newsBean.getTngou().size() > 0) {
idSwipeRefreshLayout.setVisibility(View.VISIBLE);
if (currentPage == 12) {
listData.clear();
listData.addAll(newsBean.getTngou());
mNetworkAdapter.notifyDataSetChanged();
} else {
listData.addAll(listData.size(), newsBean.getTngou());
mNetworkAdapter.notifyItemChanged(listData.size());
}
}
}
});
|
自此RxJava与Retrofit实战项目已经完结。
项目运行效果:

3 项目代码
4 后记
- 目前博客处于试写阶段,写的内容也比较简单,错误也难免出现,我想通过这个阶段总结出各个类型博客的模块,还有书写思路,最重要的是规整出什么样的博客才是对自己的知识沉淀和技术分享的“最优解”。

浙公网安备 33010602011771号