Android RxJava应用与实践

前言

本次主要讲解的内容:

1、理解RxJava里Observables的相关类型以及使用

2、RxJava在Android中的应用

在前面针对RxJava的执行流程进行了源码分析,对RxJava的运行原理有了一定的了解,简单总结一下RxJava基本就是三个元素:

Observable — Operator — Observer

  •  1、Observable,被观察者,它就好像广播一样,做一些处理后发射出一些值。

  •  2、Operator,操作符,它就像翻译员那样将数据从一种形式翻译/修改为另一种形式。

  •  3、Observer,观察者,它获得那些由被观察者发射出来的或者有操作符转译的值。

它们之间的关系:

1、RxJava里Observables的相关类型

熟悉一下RxJava的README:

https://github.com/ReactiveX/RxJava/tree/2.x

里面的Base classes部分介绍了RxJava中定义Observables相关的类,如下:

Base classes

RxJava 2 features several base classes you can discover operators on:

  • io.reactivex.Flowable: 0..N flows, supporting Reactive Streams and backpressure

  • io.reactivex.Observable: 0..N flows, no backpressure,

  • io.reactivex.Single: a flow of exactly 1 item or an error,

  • io.reactivex.Completable: a flow without items but only a completion or error signal,

  • io.reactivex.Maybe: a flow with no items, exactly one item or an error.

RxJava 2提供了几个可以发现操作符的基本类,里面相关的用法和原理都有讲解,这里我们来认识一下RxJava提供的这几个可观察类型:

在RxJava的可观察类型如下:

  • Observable

  • Flowable

  • Single

  • Completable

  • Maybe

RxJava也提供了不同类型的观察者(Observer)对应于不同的可观察类型:

  • Observer

  • SingleObserver

  • CompletableObserver

  • MaybeObserver


类型描述
Observable<T>能够发射0或n个数据,并以成功或错误事件终止。
Flowable<T>能够发射0或n个数据,并以成功或错误事件终止。支持Backpressure(背压),可以控制数据源发射的速度。
Single<T>只发射一条单一的数据,或者一条异常通知,不能发射完成通知,其中数据与通知只能发射一个。
Completable只发射一条完成通知,或者一条异常通知,不能发射数据,其中完成通知与异常通知只能发射一个。
Maybe<T>可发射一条单一的数据,以及发射一条完成通知,或者一条异常通知,其中完成通知和异常通知只能发射一个,发射数据只能在发射完成通知或者异常通知之前,否则发射数据无效。

Observable<T>:

能够发射0或n个数据,并以成功或错误事件终止。

//Observable <> Observer
private void doObservable() {
    Observable.create(new ObservableOnSubscribe<Integer>() {
        // 1. 创建被观察者 & 生产事件
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            Log.d("TAG", "发送事件 1");
            emitter.onNext(1);
            Log.d("TAG", "发送事件 2");
            emitter.onNext(2);
            Log.d("TAG", "发送事件 3");
            emitter.onNext(3);
            Log.d("TAG", "发送完成");
            emitter.onComplete();
        }
    }).subscribe(new Observer<Integer>() {
        // 2. 通过通过订阅(subscribe)连接观察者和被观察者
        // 3. 创建观察者 & 定义响应事件的行为
        @Override
        public void onSubscribe(Disposable d) {
            Log.d("TAG", "开始采用subscribe连接");
        }
        // 默认最先调用复写的 onSubscribe()

        @Override
        public void onNext(Integer value) {
            Log.d("TAG", "对Next事件" + value + "作出响应");
        }

        @Override
        public void onError(Throwable e) {
            Log.d("TAG", "对Error事件作出响应");
        }

        @Override
        public void onComplete() {
            Log.d("TAG", "对Complete事件作出响应");
        }

    });
}

Flowable<T>:

能够发射0或n个数据,并以成功或错误事件终止。

支持Backpressure(背压),可以控制数据源发射的速度。

当Observable发射了大量的值,而Observer处理不了那么多的值时,就可以用到Flowable。

这种情况下,Observable需要根据一些策略来跳过一些值,否则它会抛出异常。

可观察类型Flowable会使用策略来处理异常。

策略称为BackPressureStrategy(背压策略),异常为MissingBackPressureException(缺失背压异常)。

//Flowable <> FlowableSubscriber
private void doFlowable() {
    // 1:创建被观察者 =  Flowable
    Flowable.create(new FlowableOnSubscribe<Integer>() {
        @Override
        public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
            Log.d("TAG", "发送事件 1");
            emitter.onNext(1);
            Log.d("TAG", "发送事件 2");
            emitter.onNext(2);
            Log.d("TAG", "发送事件 3");
            emitter.onNext(3);
            Log.d("TAG", "发送完成");
            emitter.onComplete();
        }
    }, BackpressureStrategy.ERROR)// // 需要传入背压参数BackpressureStrategy
            .subscribe(new FlowableSubscriber<Integer>() {
                           // 2:创建观察者 =  Subscriber & 建立订阅关系

                           @Override
                           public void onSubscribe(Subscription s) {
                               Log.d("TAG", "onSubscribe");
                               s.request(3);
                           }

                           @Override
                           public void onNext(Integer integer) {
                               Log.d("TAG", "接收到了事件" + integer);
                           }

                           @Override
                           public void onError(Throwable t) {
                               Log.w("TAG", "onError: ", t);
                           }

                           @Override
                           public void onComplete() {
                               Log.d("TAG", "onComplete");
                           }
                       }
            );
}

Single<T>:

只发射一条单一的数据,或者一条异常通知,不能发射完成通知,其中数据与通知只能发射一个。

//Single <> SingleObserver
private void doSingle(){
    Single.create(new SingleOnSubscribe<Integer>() {
        @Override
        public void subscribe(SingleEmitter<Integer> emitter) throws Exception {
            Log.d("TAG", "发送数据 1");
            
            emitter.onSuccess(1);
//                emitter.onSuccess(2);//只发射一条单一的数据,所以此处无效
//                emitter.onError(new Exception("异常测试"));//数据与通知只能发射一个,不能与onSuccess共存
            
            //1、方法void onSuccess(T t)用来发射一条单一的数据,且一次订阅只能调用一次,不同于Observale的发射器ObservableEmitter中的void onNext(@NonNull T value)方法,在一次订阅中,可以多次调用多次发射。
            //2、方法void onError(Throwable t)等同于ObservableEmitter中的void onError(@NonNull Throwable error)用来发射一条错误通知
            //3、SingleEmitter中没有用来发射完成通知的void onComplete()方法。
            //4、方法onSuccess与onError只可调用一个,若先调用onError则会导致onSuccess无效,若先调用onSuccess,则会抛出io.reactivex.exceptions.UndeliverableException异常。
        }
    }).subscribe(new SingleObserver<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.d("TAG", "onSubscribe");
        }

        @Override
        public void onSuccess(Integer integer) {
            Log.d("TAG", "接收成功数据onSuccess:" + integer);
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }
    });
}

Completable:

只发射一条完成通知,或者一条异常通知,不能发射数据,其中完成通知与异常通知只能发射一个。

只处理 onComplete 和 onError 事件。可以看成是Rx的Runnable。

//Completable  CompletableObserver
    private void doCompletable(){
        Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(CompletableEmitter emitter) throws Exception {
                //1、方法onComplete()等同于Observale的发射器ObservableEmitter中的onComplete(),用来发射完成通知。
                //2、方法onError(Throwable e)等同于ObservableEmitter中的onError(Throwable e),用来发射异常通知。
                //3、方法onComplete与onError只可调用一个,若先调用onError则会导致onComplete无效,若先调用onComplete,则会抛出io.reactivex.exceptions.UndeliverableException异常。
                Log.d("TAG", "发送完成通知");
                emitter.onComplete();
//                emitter.onError(new Exception("异常测试"));
            }
        }).subscribe(new CompletableObserver() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onComplete() {
                Log.d("TAG", "接收完成通知");
            }

            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
            }
        });
    }

Maybe<T>:

可发射一条单一的数据,以及发射一条完成通知,或者一条异常通知,其中完成通知和异常通知只能发射一个,发射数据只能在发射完成通知或者异常通知之前,否则发射数据无效。

//Maybe MaybeObserver
private void doMaybe(){
    Maybe.create(new MaybeOnSubscribe<Integer>() {
        @Override
        public void subscribe(MaybeEmitter<Integer> emitter) throws Exception {
            emitter.onSuccess(1);//必须在onComplete()或者onError()前面执行才有效
            emitter.onSuccess(2);//只能发送单一数据,所以此处无效
            emitter.onComplete();
        }
    }).subscribe(new MaybeObserver<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onSuccess(Integer integer) {
            Log.d("TAG", "接收成功数据onSuccess:" + integer);
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onComplete() {
            Log.d("TAG", "接收完成通知onComplete:");
        }
    });
}
RxJava中的操作符

RxJava功能之所以强大,因为其对应的操作符的类型也非常多

这里推荐一个Rx和RxJava文档中文翻译项目,在git上开源 https://github.com/mcxiaoke/RxDocs

对应的中文地址参考:

https://mcxiaoke.gitbooks.io/rxdocs/content/Operators.html

2、RxJava在Android中的应用

RxAndroid的Wiki地址:

https://github.com/ReactiveX/RxAndroid/wiki

Since it cannot provide every type of binding to Android in one place, a variety of third-party add-ons are available to fill in the gaps:

翻译:由于RxAndroid不能在一个地方提供所有类型的绑定到Android,各种第三方插件可以填补这个空白:

自从rxjava出现以来,Android领域出现了各种各样基于rxjava开源的库,而作者整理了这些库:

下面主要简单介绍项目中用到的库:

1、AutoDispose:

项目中应用RxJava做网络请求时出现内存泄漏问题,前来来说说可以通过手动管理去掉订阅,先前以采用RxLifecycle来管理,发现需要继承RxActivity / RxFragment,我觉得这框架就有点侵入式了,手动管理也很费劲的,AutoDispos以完美的解决这种问题了。

只需要通过as操作符添加如下代码即可:

.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
private void doAutoDispose(){

    Observable.interval(1,TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            //AutoDispose的使用就是这句
            .as(AutoDispose.<Long>autoDisposable(AndroidLifecycleScopeProvider.from(this)))
            .subscribe(new Observer<Long>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(Long aLong) {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });
}
2、RxPermissions:

RxPermissions并没有在项目中应用,可以引入使用一下,现在运用的系统方法,需要定义 请求 相应,这个库通过链式编程就可以动态获取权限:相关用法简单列子:

/**
 * request示例:
 * 不支持返回权限名;
 * 返回的权限结果:全部同意时值true,否则值为false
 */
public void doRxPermissionsRequest() {
    RxPermissions rxPermissions = new RxPermissions(this);
    rxPermissions.request(Manifest.permission.CAMERA)
            .subscribe(new Consumer<Boolean>() {
                @Override
                public void accept(Boolean granted) throws Exception {
                    Log.i("hyl", "申请结果:" + granted);
                }
            });

}

/**
 * requestEach示例:
 * 把每一个权限的名称和申请结果都列出来
 */
public void doRxPermissionsRequestEach(View view) {
    RxPermissions rxPermissions = new RxPermissions(this);
    rxPermissions.requestEach(Manifest.permission.CAMERA)
            .subscribe(new Consumer<Permission>() {
                @Override
                public void accept(Permission permission) throws Exception {
                    Log.i("hyl", "权限名称:" + permission.name + ",申请结果:" + permission.granted);
                }
            });
}

/**
 * requestEachCombined示例:
 * 返回的权限名称:将多个权限名合并成一个
 * 返回的权限结果:全部同意时值true,否则值为false
 */
public void doRxPermissionsRequestEachCombined(View view) {
    RxPermissions rxPermissions = new RxPermissions(this);
    rxPermissions.requestEachCombined(Manifest.permission.CAMERA)
            .subscribe(new Consumer<Permission>() {
                @Override
                public void accept(Permission permission) throws Exception {
                    Log.i("hyl", "权限名称:" + permission.name + ",申请结果:" + permission.granted);
                }
            });
}

/**
 * ensure示例:
 * 必须配合rxjava,回调结果与request一样
 */
public void doRxPermissionsEnsure(View view) {
    RxPermissions rxPermissions = new RxPermissions(this);
    Observable.timer(10, TimeUnit.MILLISECONDS)
            .compose(rxPermissions.ensure(Manifest.permission.CAMERA))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Boolean>() {
                @Override
                public void accept(Boolean aBoolean) throws Exception {
                    Log.i("hyl","申请结果:"+aBoolean);
                }
            });
}

/**
 * ensureEach示例:
 * 必须配合rxjava,回调结果跟requestEach一样
 */
public void doRxPermissionsEnsureEach(View view) {
    RxPermissions rxPermissions = new RxPermissions(this);
    //
    Observable.timer(10, TimeUnit.MILLISECONDS)
            .compose(rxPermissions.ensureEach(Manifest.permission.CAMERA))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Permission>() {
                @Override
                public void accept(Permission permission) throws Exception {
                    Log.i("hyl","权限名称:"+permission.name+",申请结果:"+permission.granted);
                }
            });
}

/**
 * ensureEachCombined示例:
 * 必须配合rxjava,回调结果跟requestEachCombined一样
 */
public void doRxPermissionsEnsureEachCombined(View view) {
    RxPermissions rxPermissions = new RxPermissions(this);
    Observable.timer(10, TimeUnit.MILLISECONDS)
            .compose(rxPermissions.ensureEachCombined(Manifest.permission.CAMERA))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Permission>() {
                @Override
                public void accept(Permission permission) throws Exception {
                    Log.i("hyl","权限名称:"+permission.name+",申请结果:"+permission.granted);
                }
            });
}
3、RxBinding:

首先明确RxBinding是用来帮助控件处理各种点击事件的开源库,并不提供控件初始化的功能,当时第一印象以为和butterknife是一类东西,其实不然。

注意:项目中引入了RxJava再引入RxBinding报错,应为依赖RxBinding就不需要再依赖RxJava了,内部已经包含了。

/**
 * 2s内只允许执行一次点击事件方法,
 * 可以有效避免按钮被快速重复点击
 */
@SuppressLint("CheckResult")
private void doFastClick() {
    RxView.clicks(mTvBinding)
            .throttleFirst(2, TimeUnit.SECONDS) //两秒钟之内只取一个点击事件,防重复点击操作
            .subscribe(new Consumer<Unit>() {
                @Override
                public void accept(Unit unit) throws Exception {
                    Toast.makeText(RxBindingActivity.this, "触发点击", Toast.LENGTH_SHORT).show();
                }
            });
}

/**
 * 通过rxbinding和rxPermissions的结合,实现点击事件过程中,
 * 确保点击时候要求的相机运行时权限已被申请的前提下才去执行具体的点击事件
 */
@SuppressLint("CheckResult")
private void doClickPermissions() {
    RxPermissions rxPermissions = new RxPermissions(this);
    RxView.clicks(mTvClickPermission)
            .compose(rxPermissions.ensure(Manifest.permission.CAMERA))
            .subscribe(new Consumer<Boolean>() {
                @Override
                public void accept(Boolean granted) throws Exception {
                    //可根据granted设置点击执行内容
                    Log.i("hyl", "申请结果:" + granted);
                }
            });
}

RxView除了可以监听clicks时间还可以进行长按监听、绘制监听、拖拽监听、滑动时触发、EditText输入监听等等,再结合RxJava操作符的功能进行拓展使用。

4、Rx Preferences:

翻译一下rx-preferences的readme:

https://github.com/f2prateek/rx-preferences/blob/master/README.md

Rx Preferences

Reactive SharedPreferences for Android.

Usage(用法)

Create an RxSharedPreferences instance which wraps a SharedPreferences:

翻译-->创建包装 SharedPreferences的RxSharedPreferences 实例:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
RxSharedPreferences rxPreferences = RxSharedPreferences.create(preferences);

Hint: Keep a strong reference on your RxSharedPreferences instance for as long as you want to observe them to prevent listeners from being GCed.

翻译-->提示:只要你想观察你的RxSharedPreferences 实例,就可以对它的进行强引用,以防止侦听者被拒绝。

Create individual Preference objects: 翻译-->创建单个 Preference 对象:

Preference<String> username = rxPreferences.getString("username");
Preference<Boolean> showWhatsNew = rxPreferences.getBoolean("show-whats-new", true);

Observe changes to individual preferences:

翻译-->观察对preferences(个人偏好)设置的更改:

username.asObservable().subscribe(new Action1<String>() {
  @Override public void call(String username) {
    Log.d(TAG, "Username: " + username);
  }
}
5、ReactiveNetwork:

ReactiveNetwork是一个监听网络连接状态与WiFi信号强度的库,我们一般都是都是通过监听系统广播来实现网络状态变化的监听事件。

/**
 * 监听网络状态
 */
@SuppressLint("CheckResult")
private void doReactiveNetwork() {

    ReactiveNetwork
            .observeNetworkConnectivity(this)
            .subscribeOn(Schedulers.io())
            // anything else what you can do with RxJava
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Connectivity>() {
                @Override
                public void accept(Connectivity connectivity) throws Exception {
                    // do something with connectivity
                    // you can call connectivity.state();
                    // connectivity.type(); or connectivity.toString();
                }
            });
}

/**
 * 实现网络是否连接的监听
 */
private void doReactiveNetWorkisConnect(){
    ReactiveNetwork.observeInternetConnectivity()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Boolean>() {
                @Override
                public void accept(Boolean isConnected) throws Exception {
                    Toast.makeText(ReactiveNetworkActivity.this, isConnected.toString(), Toast.LENGTH_SHORT).show();
                }
            });
}

还有其它相关的库,这里选了几个项目中通常都会用到的,还有一些可以去尝试使用一下。谢谢!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值