在Android中使用响应式编程

作者: 双鱼大猫 | 来源:发表于2016-11-12 17:56 被阅读238次

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

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

    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中使用响应式编程

        本文链接:https://www.haomeiwen.com/subject/rbuqpttx.html