先来看看RxJava和Retrofit的一个结合的例子
我们有两个方法,获取不同的数据

public interface WeatherService {
@GET("adat/sk/{cityId}.html")//注意参数名称必须一样 @Path表示将参数进行匹配,与{}结合使用
Observable<WeatherInfo> getWeatherInfo(@Path("cityId") String cityId);
Observable<WeatherInfo> getWeatherInfo2(@Path("cityId") String cityId);
}

我们可以将这两个请求并发的发出,并且等待两个结果都返回之后再做处理

Observable.zip(weatherService.getWeatherInfo("101010100"),
weatherService.getWeatherInfo2("101010102"), new Func2<WeatherInfo, WeatherInfo, InfoResult>() {
@Override
public InfoResult call(WeatherInfo weatherInfo, WeatherInfo weatherInfo2) {
return null;//合并结果
}
}).subscribe(new Action1<InfoResult>() {
@Override
public void call(InfoResult infoResult) {
//处理最终结果
}
});
}
class InfoResult{
public List<InfoResult> list;
}
public InfoResult mergeResult(){
return null;
}

对以前代码的封装

public Object oldMethod(){
return null;
}
Observable<Object> newMethod(){
return Observable.just(oldMethod());
}

如果老的方法容易发生阻塞怎么办

public Object oldMethod(){
return null;
}
Observable<Object> newMethod(){
return Observable.defer(new Func0<Observable<Object>>() {
@Override
public Observable<Object> call() {
return Observable.just(oldMethod());
}
});

注意,这里使用了defer操作符,目的就是为了延迟事件源事件的发出知道订阅者订阅到了观察者上面。官方介绍如下

The defer Observer allows you to defer or delay emitting items from an Observable until such time as an
* Observer subscribes to the Observable.

生命周期

1.在configuration改变(比如转屏)之后继续之前的Subscription。

比如你使用Retrofit发出了一个REST请求,接着想在listview中展示结果。如果在网络请求的时候用户旋转了屏幕怎么办?你当然想继续刚才的请求,但是怎么搞?

2.Observable持有Context导致的内存泄露

这个问题是因为创建subscription的时候,以某种方式持有了context的引用,尤其是当你和view交互的时候,这太容易发生!如果Observable没有及时结束,内存占用就会越来越大。
不幸的是,没有银弹来解决这两个问题,但是这里有一些指导方案你可以参考。

第一个问题的解决方案就是使用RxJava内置的缓存机制,这样你就可以对同一个Observable对象执行unsubscribe/resubscribe,却不用重复运行得到Observable的代码。cache() (或者 replay())会继续执行网络请求(甚至你调用了unsubscribe也不会停止)。这就是说你可以在Activity重新创建的时候从cache()的返回值中创建一个新的Observable对象。

Observable<Photo> request = service.getUserPhoto(id).cache();
Subscription sub = request.subscribe(photo -> handleUserPhoto(photo));

// ...When the Activity is being recreated...
sub.unsubscribe();

// ...Once the Activity is recreated...
request.subscribe(photo -> handleUserPhoto(photo));

注意,两次sub是使用的同一个缓存的请求。当然在哪里去存储请求的结果还是要你自己来做,和所有其他的生命周期相关的解决方案一延虎,必须在生命周期外的某个地方存储。(retained fragment或者单例等等)。

第二个问题的解决方案就是在生命周期的某个时刻取消订阅。一个很常见的模式就是使用CompositeSubscription来持有所有的Subscriptions,然后在onDestroy()或者onDestroyView()里取消所有的订阅。

private CompositeSubscription mCompositeSubscription
= new CompositeSubscription();

private void doSomething() {
mCompositeSubscription.add(
AndroidObservable.bindActivity(this, Observable.just("Hello, World!"))
.subscribe(s -> System.out.println(s)));
}

@Override
protected void onDestroy() {
super.onDestroy();

mCompositeSubscription.unsubscribe();
}

你可以在Activity/Fragment的基类里创建一个CompositeSubscription对象,在子类中使用它。

注意! 一旦你调用了 CompositeSubscription.unsubscribe(),这个CompositeSubscription对象就不可用了, 如果你还想使用CompositeSubscription,就必须在创建一个新的对象了。