在Android中使用响应式编程

From: http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/

在Android中使用响应式编程_第1张图片

嘿,小伙伴们,今天,我继续死磕自己。

RxAndroid是RxJava的一个针对Android平台的扩展,它包含了一些能简化Android开发的工具。

首先,AndroidSchedulers提供了针对Android的线程系统的调度器。需要在UI线程中运行某些代码?很简单,只需要使用AndroidSchedulers.mainThread();

retrofitService.getImage(url)

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedules.mainThread())

.subscribe(bitmap - > myImageView.setImageBitmap(bitmap));

如果你已经创建了自己的Handler,你可以使用Handler.ThreadScheduler1将一个调度器链接到你的handler上。

接着要介绍的就是AndroidObservable,他提供了很多的功能来配合Android的生命周期。

bindActivity()和bindFragment()方法默认使用AndroidSchedulers.mainThread()来执行观察者代码,这两个方法会在Activity或者Fragment结束的时候通知被观察者发出新的消息。

AndroidObservable.bindActivit(this,retrofitService.getImage(url))

.subscribeOn(Schedulers.io())

.subscribe(bitmap - > myImageView.setImageBitmap(bitmap));

我自己也很喜欢AndroidObservable.fromBrodcast()方法,它允许你创建类似于BroadcastReceiver的Observable对象。下面的例子展示了如何在网络变化的时候被通知到:

InterFilter filter = new IntentFilter(ConnectivityManager.COMMECTIVITY_ACTION);

AndroidObservable.fromBroadcast(context,filter)

.subscribe(intent - > handleConectivityChange(intent));

最后要介绍的是ViewObservable,使用它可以给View添加一些绑定。如果你想每次点击View的时候都收到一个事件,可以使用ViewObservable.clicks(), 或者你想监听TextView内容的变化,可以使用ViewObservable.text().

ViewObservable.clicks(mCardNameEditText,false)

.subscribe(view - > handleClick(view));

Retrofit

大名鼎鼎的Retrofit库内置了对RxJava的支持。通常可以通过使用一个Callback对象来获取异步的结果:

@GET("/user/{id}/photo") void getUserPhoto(@Path("id") int id, Callback cb);

使用RxJava, 你可以直接返回一个Observable对象。

@GET("/user/{id}/photo")

Observable getUserPhoto(@Path("id") int id);

现在你可以随意使用Observable对象了。你不仅可以获取数据,还可以进行变换。

Retrofit对Observable的支持使得它可以将很多个简单的REST请求结合起来。比如我们有一个请求是获取照片的,还有一个请求是获取元数据的,我们就可以将这两个请求并发的发出,并且等待两个结果都返回之后再处理:

Observavle.zip(

service.getUserPhoto(id),

service.getPhotoMetadata(id),

(photo, metadata) - > createPhotoWithData(photo,metadata))

.subscribe(photoWithData - > showPhoto(photoWithData));

在之前的文章我展示过一个类似的例子 (使用flatMap())。这里我只是想展示使用RxJava + Retrofit 可以多么简单的组合多个REST请求。

遗留代码,运行极慢的代码

Retrofit可以返回Observable对象,但是如果你使用的别的库并不支持这样怎么办?或者说一个内部的内码,你想把他们转换成Observable,有什么简单的方法吗?

觉大多数时候,Observable.just() 和 Observable.from() 能够帮助你从遗留的代码中创建 Observable 对象:

private Object oldMethod() {....}

把原来的老的方法返回一个Object类型,然后把这个返回的对象放入Observable.just()中去

public Observable newMethod(){

return Observable.just(oldMethod());

}

上面的例子中如果oldMethod()足够快是没有什么问题的,但是如果很慢呢?调用oldMethod()将会阻塞主他所在的线程。

为了解决这个问题,可以参考我一直使用的方法  使用defer() 来包装在线程中的运行缓慢的代码:

private Object slowBlockingMethod(){...}

public Observable newMethod(){

return Observavoe.defer( () ->

Observable.just(slowBlockingMethod())

);

}

现在,newMethod() 的调用就不会阻塞了,除非你订阅了返回的observable对象。

生命周期

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

Observavle request = service.getUserPhoto(id).cache();

Subscription sub = request.subscribe(photo - > handleUserPhoto(photo));

//当这个Activity  生命周期结束时候, sub.unsubscribe();

// 当这个Activity开始这个生命周期的时候,sub.subscribe();

request.subscribe(photo - > handlerUsdrPhoto(photo));

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

复合订阅关系的处理

一个很常见的模式就是使用CompositeSubscription来持有所有的Subscriptions, 然后在onDestory()或者onDestoryView() 里取消所有的订阅。

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 onDestory(){

mCompositeSubscription.unsubscribe();

}

}

更多内容请关注我的个人微信公众号:前端开发技术栈

在Android中使用响应式编程_第2张图片

你可能感兴趣的:(在Android中使用响应式编程)