RxJava构成
简述
RxJava = Observable + Operator + Scheduler + Observer?
Observable*
可观察数据源有哪些特征,
- Usually do work when you start or stop listening
- Synchronous or asynchronous
- Single item,many items,or empty
- Terminates with an error or succeeds to completion
- May never terminate!
- Just an implemention of the Observer pattern
哪些可称为可观察数据源
如何创建建Observable
- Observable.just("Hello")
- Observable.fromArray("Hello","Hello2")
- Observable.fromCallable{"Hello"}
- Observable.create{ it.onNext("Hello")}
- Observable.Interval(200)
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("Hello");
emitter.onComplete();
}
})
Observable.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception {
return "Hello";
}
});
同时在Android使用场景中:
- RxView.clicks(view) : Observable
- login(@Body LoginReqParams) : Observable
- RxPermissions.request(READ_PHONE_STATE) : Observable
- Creating Observables : create,just,from
- Transforming Observables :Map,FlatMap
- Filtering Observables:Filter,Debouncee,Distinct,Skip
- Combining Observables : Merge,Zip,CombineLatest
- Error Handling Operators: Catch,Retry
- Observable Utility Operators: Delay,TimeInterval,ObserveOn,SubscribeOn
- Conditional and Boolean Operators : All,Contains,TkeWhile
- Mathematical and Aggregate Operators : Average,Count,Max
- Connectable Observable Operators : Connect,Replay
- Operators to Convert Observables : To
Operator 操作符
介绍
ReactiveX的每种特定语言实现都实现了一组操作符。大致分为以下分类:
map
fliter
Scheduler 线程调度
subscribeOn
指定订阅过程运行的线程,同时控制了Observable,Observer。
我们先看一段代码运行结果。
println("in main:${Thread.currentThread()}")
Observable.create<Int> {
println("in create:${Thread.currentThread()}");
it.onNext(1) }
//.subscribeOn(Schedulers.newThread())
.subscribe { println("in next :${Thread.currentThread()} $it") }
//运行结果
in main:Thread[main,5,main]
in create:Thread[main,5,main]
in next :Thread[main,5,main] 5
加上subscribeOn之后,发现subscribeOn的上游和下游运行线程都发生了变化。
println("in main:${Thread.currentThread()}")
Observable
.create<Int> {
println("in create:${Thread.currentThread()}");
it.onNext(1) }
.subscribeOn(Schedulers.newThread())
.subscribe { println("in next :${Thread.currentThread()} $it") }
//运行结果
in main:Thread[main,5,main]
in create:Thread[RxNewThreadScheduler-1,5,main]
in next :Thread[RxNewThreadScheduler-1,5,main] 5
observeOn
指定观察者所在线程。
我们先看一段代码运行结果。
println("in main:${Thread.currentThread()}")
Observable
.create<Int> {
println("in create:${Thread.currentThread()}");
it.onNext(1) }
//.observeOn(Schedulers.newThread())
.subscribe { println("int next :${Thread.currentThread()} $it") }
//运行结果
in main:Thread[main,5,main]
in create:Thread[main,5,main]
in next :Thread[main,5,main] 5
加上observeOn之后,发现observeOn下游运行线程都发生了变化。
println("in main:${Thread.currentThread()}")
Observable.create<Int> {
println("in create:${Thread.currentThread()}");
it.onNext(1) }
.observeOn(Schedulers.newThread())
.subscribe { println("in next :${Thread.currentThread()} $it") }
//运行结果
in main:Thread[main,5,main]
in create:Thread[main,5,main]
in next :Thread[RxNewThreadScheduler-1,5,main] 5
Observer 观察者
APP中使用场景
网络请求:Retrofit+RxJava
@POST("/content/user/info")
Observable<BaseResponse<UserInfo>> userInfo_Ob(@Body UserInfoReq req);
这里有一段我们使用操作符的代码,app初始化时同步服务端数据
//app初始化时同步服务端数据,
fun checkRequiredObservable(): Observable<PersonRequiredInfo> {
//后续需要的个人信息
var personRequiredInfo = PersonRequiredInfo()
val allObservables = arrayListOf(
...
//一系列独立的请求
appTabSetting(),//底部tab配置
userInfoObservable(),//用户信息
queryBindConfig(),//用户绑定账号信息
syncBabyInfoObservable(userId) //同步宝宝信息
...
)
var zipObservable = Observable.zip(allObservables) {
return@zip personRequiredInfo
}
return apolloAppConfig()//先获取apollo配置信息,同时保存配置
.flatMap {zipObservable } //并行上面一系列请求
.onErrorReturn { personRequiredInfo }
.doOnNext {registerUserSuperProperties()}
.compose(RxHelper.io2MainThread())
}
private fun syncBabyInfoObservable(): Observable<Any> {
return getBabyInfoObservable() //先获取服务端宝宝信息
.flatMap { updateBabyInfoObservable() } //本地与服务端比较,如果需要上传则上传
.flatMap { getBabyInfoObservable().map { Any() } }//再次获取同步后的宝宝信息
.onErrorReturn { Any()}
}
现有接口状况的情况下,很难想象,如果没有RxJava我该如何组合这些请求。
防抖(debounce)与节流(throttle)
Returns an Observable that mirrors the source ObservableSource, except that it drops items emitted by the source ObservableSource that are followed by newer items before a timeout value expires. The timer resets on each emission.
throttleFirst
Returns an Observable that emits only the first item emitted by the source ObservableSource during sequential time windows of a specified duration.
View重复点击
RxView.clicks(container)
.throttleFirst(800,TimeUnit.MILLISECONDS)
.subscribe { onclick() }
搜索防抖
RxTextView.textChanges(etSearch)
.debounce(searchDebounceTime, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { goSearch(chars) }
页面刷新频率控制
class RefreshDebounce {
private var rxEmitter: ObservableEmitter<Long>? = null
private var observable = Observable
.create<Long> { rxEmitter = it }
.debounce(1000L, TimeUnit.MILLISECONDS)
constructor(consumer: (Long) -> Unit? ){
observable.subscribe { consumer.invoke(it) }
}
fun callRefresh() = rxEmitter?.onNext(System.currentTimeMillis())
}
//使用
var refreshDebounce = RefreshDebounce { println("refresh:$it") }
refreshDebounce.callRefresh()
定时/延时执行
private void startCountDown15Min() {
countDown15MinDisposable = Observable.timer(900, TimeUnit.SECONDS)
subscribe(aLong -> Log.i(TAG, "倒计时时间到"));
}
private void cancelCountDown15Min() {
if (countDown15MinDisposable != null && !countDown15MinDisposable.isDisposed()) {
countDown15MinDisposable.dispose();
}
}
系统权限申请
new RxPermissions(activity)
.request(Manifest.permission.READ_PHONE_STATE)
.subscribe(aBoolean -> Log.d(TAG,"result:"+aBoolean)