RxJava从入门到不离不弃(八)——使用场景

451 阅读5分钟

RxJava系列的文章已经写了有七篇了,相信读者已经对它比较熟悉了。

介绍了那么多,那么到底RxJava在真实开发中会有哪些地方用到呢?今天和大家介绍一下它的经典使用场景。

RxJava + Retrofit

Retrofit 除了提供了传统的 Callback 形式的 API,还有 RxJava 版本的 Observable 形式 API。下面我用对比的方式来介绍 Retrofit 的 RxJava 版 API 和传统版本的区别。

以获取一个 MovieEntity 对象的接口作为例子。使用Retrofit 的传统 API,你可以用这样的方式来定义请求:

@GET("top250")
Call<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);//正常返回Call对象

我们来写getMovie方法的代码:

//进行网络请求
    private void getMovie(){
        String baseUrl = "https://api.douban.com/v2/movie/";
    
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    
        MovieService movieService = retrofit.create(MovieService.class);
        Call<MovieEntity> call = movieService.getTopMovie(0, 10);
        call.enqueue(new Callback<MovieEntity>() {
            @Override
            public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
                resultTV.setText(response.body().toString());
            }
    
            @Override
            public void onFailure(Call<MovieEntity> call, Throwable t) {
                resultTV.setText(t.getMessage());
            }
        });
    }

以上为没有经过封装的、原生态的Retrofit写网络请求的代码。

而使用 RxJava 形式的 API,定义同样的请求是这样的:

@GET("top250")
Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);//RxJava返回Observable对象

Retrofit本身对Rxjava提供了支持,getMovie方法改为:

//进行网络请求
    private void getMovie(){
        String baseUrl = "https://api.douban.com/v2/movie/";
    
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//提供RXjava支持
                .build();
    
        MovieService movieService = retrofit.create(MovieService.class);
    
        movieService.getTopMovie(0, 10)//返回Observable对象
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<MovieEntity>() {
                    @Override
                    public void onCompleted() {
                        Toast.makeText(MainActivity.this, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        resultTV.setText(e.getMessage());
                    }
    
                    @Override
                    public void onNext(MovieEntity movieEntity) {
                        resultTV.setText(movieEntity.toString());
                    }
                });
    }

这样基本上就完成了Retrofit和Rxjava的结合,大家可以自己进行封装;那么用上了RxJava,我们就可以用它强大的操作符来对数据进行处理和操作,各位看官可以具体去实现,我在这里不做多做赘述。

RxBinding

RxBinding 是 Jake Wharton 的一个开源库,它提供了一套在 Android 平台上的基于 RxJava 的 Binding API。所谓 Binding,就是类似设置 OnClickListener 、设置 TextWatcher 这样的注册绑定对象的 API。

举个设置点击监听的例子。使用 RxBinding ,可以把事件监听用这样的方法来设置:

Button button = ...;
RxView.clickEvents(button) // 以 Observable 形式来反馈点击事件
    .subscribe(new Action1<ViewClickEvent>() {
        @Override
        public void call(ViewClickEvent event) {
            // Click handling
        }
    });

看起来除了形式变了没什么区别,实质上也是这样。甚至如果你看一下它的源码,你会发现它连实现都没什么惊喜:它的内部是直接用一个包裹着的 setOnClickListener() 来实现的。然而,仅仅这一个形式的改变,却恰好就是 RxBinding 的目的:扩展性。通过 RxBinding 把点击监听转换成 Observable 之后,就有了对它进行扩展的可能。扩展的方式有很多,根据需求而定。一个例子是前面提到过的 throttleFirst() 操作符,用于去抖动,也就是消除手抖导致的快速连环点击:

RxView.clickEvents(button)
    .throttleFirst(500, TimeUnit.MILLISECONDS)
    .subscribe(clickAction);

如果想对 RxBinding 有更多了解,可以去它的 GitHub 项目 下面看看。

RxLifecyle

RxLifecycle 配合 Activity/Fragment 生命周期来管理订阅的。 由于 RxJava Observable 订阅后(调用 subscribe 函数),一般会在后台线程执行一些操作(比如访问网络请求数据),当后台操作返回后,调用 Observer 的 onNext 等函数,然后在 更新 UI 状态。 但是后台线程请求是需要时间的,如果用户点击刷新按钮请求新的微博信息,在刷新还没有完成的时候,用户退出了当前界面返回前面的界面,这个时候刷新的 Observable 如果不取消订阅,则会导致之前的 Activity 无法被 JVM 回收导致内存泄露。 这就是 Android 里面的生命周期管理需要注意的地方,RxLifecycle 就是用来干这事的。比如下面的示例:

myObservable
    .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
    .subscribe();

这样Activity在destroy的时候就会自动取消这个observer。

RxBus

RxBus并不是一个库,而是一种模式。相信大多数开发者都使用过EventBus或者Otto,作为事件总线通信库,如果你的项目已经加入RxJava和EventBus,不妨用RxBus代替EventBus,以减少库的依赖。RxJava也可以轻松实现事件总线,因为它们都依据于观察者模式。

RxPermission

RxPermission是基于RxJava开发的用于帮助在Android 6.0中处理运行时权限检测的框架。在Android 6.0中,系统新增了部分权限的运行时动态获取。而不再是在以前的版本中安装的时候授予权限。

总结

简而言之Rxjava是一个很牛逼的库,如果你的项目中还没有使用RxJava的话,建议可以尝试去集成使用;对大多数人而已RxJava是一个比较难上手的库了,不亚于Dagger的上手难度;不过当你认识学习使用过了,你就会发现RxJava的魅力所在;如果看一遍没有看懂的童鞋,建议多看几次;动手写写代码,我想信本文可以给到你们一些帮助;你们真正的体会到什么是 从入门到放弃再到不离不弃 ;这就是RxJava的魅力所在。

系列文章

RxJava从入门到不离不弃(一)——基本概念和使用

RxJava从入门到不离不弃(二)——简化代码

RxJava从入门到不离不弃(三)——转换操作符

RxJava从入门到不离不弃(四)——过滤操作符

RxJava从入门到不离不弃(五)——do操作符

RxJava从入门到不离不弃(六)——Scheduler线程调度

RxJava从入门到不离不弃(七)——groupBy

更多精彩内容,欢迎关注我的微信公众号——Android机动车