文章目录
- RxJava用例指南
- 转换成可观察对象 :star:(Riddle1)
- 变换数据:star: (Riddle2)
- 过滤数据 :star: (Riddle3)
- 状态切换 (Riddle4)
- 多个可观察对象合并最新状态:star: (Riddle5)
- 并行执行网络请求,再合并结果:star: (Riddle6)
- 数据去重 :star: (Riddle7)
- 延迟:star: (Riddle8)
- 条件取消:star: (Riddle9)
- 多个数据打平 :star:(Riddle10)
- 点击防抖:star: (Riddle11)
- 错误返回默认值 :star: (Riddle12)
- 连续相同的去重 (Riddle13)
- 重试 (Riddle14)
- 并行获取 按顺发射 (Riddle15)
- 转换,停止之前未完成的 (Riddle16)
- 懒执行 (Riddle17)
- source 多选一 ,竞速 (Riddle18)
- 监听器转换成Observable (Riddle19)
- 按发射顺序合并 :star:(Riddle 20)
- 只取第一个值 :star:(Riddle 21)
- 分组发射:star: (Riddle 22)
- 类型转换 :star:(Riddle 23)
- 计数 :star:(Riddle 24)
- 默认值 (Riddle 25)
- 发送延时:star: (Riddle 26)
- 不同阶段调用:star:(Riddle 27 , 28 ,29 ,30)
- 重复发送 (Riddle31)
- 超时设置 (Riddle32)
- 线程切换 :star:(Riddle33 , 34)
- 条件切换发送源 (Riddle35)
- 防抖操作 :star:(Riddle36)
- 异常恢复:star:(Riddle37)
- 双击检测:star: (Riddle100)
- 倒计时:star: (Riddle101)
- 参考
RxJava用例指南
开篇灵魂拷问❓ : 你真的会RxJava吗? 反正我是不会
本文会详细介绍使用场景,不会讲原理,主要参考Github RxRiddle kotlin项目
转换成可观察对象 ⭐️(Riddle1)
Observable.just(value)
变换数据⭐️ (Riddle2)
Observable.just(1,2,3).map { it+1 }.subscribe(::print)
// 结果 2,3,4
过滤数据 ⭐️ (Riddle3)
Observable.just(1,2,3).filter { it % 2 == 0 }.subscribe(::print)
// 结果 2
状态切换 (Riddle4)
val subject = PublishSubject.create<Unit>()
subject.scan(false) { t1, _ -> !t1}.subscribe(::print)
subject.onNext(Unit) // 结果 true
subject.onNext(Unit) // 结果 false
多个可观察对象合并最新状态⭐️ (Riddle5)
val first = BehaviorSubject.createDefault(0)
val second = BehaviorSubject.createDefault(0)
Observable.combineLatest(first, second,
BiFunction<Int, Int, Int> { t1, t2 -> t1 + t2 }
).subscribe(::print) // 结果 0
fisrt.onNext(3) // 结果 3
second.onNext(6) // 结果 9
fisrt.onNext(7) // 结果 13
并行执行网络请求,再合并结果⭐️ (Riddle6)
//网络请求1 first
//网络请求2 second
Single.zip(first, second, BiFunction<Int, Int, Pair<Int, Int>> { t1, t2 -> t1 to t2})
数据去重 ⭐️ (Riddle7)
Observable.just(1,2,3,1,2,3).distinct().subscribe(::print) // 结果 1,2,3
延迟⭐️ (Riddle8)
Observable.just(1,2,3).delaySubscription(200,TimeUnit.MILLISECONDS).subscribe(::print)
// 延迟200ms, 返回结果 1,2,3
条件取消⭐️ (Riddle9)
触发器触发时取消,如退出登录时,取消轮询
val trigger = PublishSubject.create<Unit>()
val main = Observable.interval(1, SECONDS)
main.takeUtil(trigger).subcribe(::pirnt) //间隔一秒输出 1 2 3 4 ...
trigger.onNext(Unit) // 停止输出
多个数据打平 ⭐️(Riddle10)
如获取列表后,再请求详情
Observable.just(1,2).flatMap({Observable.just("1","2")}){ t1, t2 -> t1 to t2}
.subcribe { print(it)}
//结果 (1, 1)(1, 2)(2, 1)(2, 2)
点击防抖⭐️ (Riddle11)
// 使用到RxBinding
button.clicks().throttleFirst(300,TimeUnit.MILLISECONDS).subscribe{
System.out.println("clicked")
}
错误返回默认值 ⭐️ (Riddle12)
Observable.create {
it.onNext(1)
it.onNext(2)
it.onError(RuntimeException())
})
.onErrorReturnItem(5 )
.subcribe(::pirnt) // 结果 1 2 5
连续相同的去重 (Riddle13)
Observable.just(1, 2, 1, 1, 4, 4, 4, 5, 4)
.distinctUntilChanged()
.subcribe(::pirnt) // 结果 1 2 1 4 5 4
重试 (Riddle14)
Single.just(Single.fromCallable {println("hello")}
throw UnsupportedOperationException()
).retry(2) {
it !is IllegalArgumentException
}
并行获取 按顺发射 (Riddle15)
如缓存与网络请求, 同时进行操作,按顺序返回
Observable.concatEager(listOf(first,second))
转换,停止之前未完成的 (Riddle16)
map的高级版本,自动抛弃之前未完成的, 搜索框输入
first.switchMapSingle { function.invoke(it) }
懒执行 (Riddle17)
subscribe时候 执行
Observable.fromCallable(function)
source 多选一 ,竞速 (Riddle18)
先返回的作为后续的source, 比如多个服务器地址时,选择网速快的
Observable.ambArray(first,second)
监听器转换成Observable (Riddle19)
Observable.create {
interaction.listener = it::onNext
it.setCancellable { interaction.listener = null }
}
按发射顺序合并 ⭐️(Riddle 20)
first.mergeWith(second)
只取第一个值 ⭐️(Riddle 21)
Observable.just(1, 2, 3).blockingFirst().subscribe(::println)
//结果 1
分组发射⭐️ (Riddle 22)
Observable.range(0, 10).buffer(2,3).subscribe(::println) // 发送 1 2 ,跳过第三个
//结果 [0,1] [3,4] [6,7] [9]
类型转换 ⭐️(Riddle 23)
Observable.just<Any>("bar", "foo").cast(String::class.java)
计数 ⭐️(Riddle 24)
Observable.just(Unit, Unit).count().subscribe(::print)
//结果 2
默认值 (Riddle 25)
Observable.empty<Int>().defaultIfEmpty(5).subscribe(::print)
//结果5
Observable.just(1, 3).defaultIfEmpty(5).subscribe(::print)
//结果 1 3
发送延时⭐️ (Riddle 26)
source.delay(300,TimeUnit.MILLISECONDS)
不同阶段调用⭐️(Riddle 27 , 28 ,29 ,30)
如日志打印
source.doOnNext { // whatever action you want }
.doOnComplete{// whatever action you want }
.doOnError{// whatever action you want }
// doOnComplete doOnError可以合并 doOnTerminate
.doOnSubscribe{// whatever action you want }
重复发送 (Riddle31)
val subscribeCall = AtomicInteger()
val o = Observable.create<Int> {
when (subscribeCall.getAndIncrement()) {
0 -> listOf(1, 2, 3).forEach(it::onNext)
1 -> listOf(6, 7, 8).forEach(it::onNext)
2 -> listOf(15, 16).forEach(it::onNext)
}
it.onComplete()
}
o.repeat(3).subscribe(::print)
//结果 1, 2, 3, 6, 7, 8, 15, 16
超时设置 (Riddle32)
timeout(3,TimeUnit.SECONDS) //超时抛出TimeoutException异常
线程切换 ⭐️(Riddle33 , 34)
val first = Schedulers.from(Executors.newSingleThreadExecutor { Thread(it, "First thread") })
val second = Schedulers.from(Executors.newSingleThreadExecutor { Thread(it, "Second thread") })
source.observeOn(first) //观察线程 下游的都切换到该线程
.map{ }
.subscribeOn(second) //订阅线程 上下游的都切换到该线程
.filter{}
.subscirbe()
条件切换发送源 (Riddle35)
如缓存未命中,走网络请求
val first = Maybe.empty<String>()
val second = Single.just("Second")
first.switchIfEmpty(second).subscribe(::print) //结果 Second
防抖操作 ⭐️(Riddle36)
val source = PublishSubject.create<String>()
source.debounce(milliseconds,TimeUnit.MILLISECONDS).subscribe(::print)
source.onNext("1")
source.onNext("2")
source.onNext("3")
说下throttle /debounce 差异
- debounce 两次事件间隔时间
- throttle 两个时间段的间隔时间, 如间隔1s , [0,1] 在0.999s发射 [1,2] 在1.001s发射
异常恢复⭐️(Riddle37)
Observable.concat(Observable.just(true), Observable.error(IOException()))
.onErrorResumeNext { t: Throwable ->
when (t) {
is IOException -> Observable.just(false)
else -> Observable.error(t)
}
}
.subscribe(::print )
//结果 true false
双击检测⭐️ (Riddle100)
val source =Observable.fromIterable(listOf(0L, 200L, 400L, 700L, 800L))
.flatMapSingle { Single.timer(it, MILLISECONDS).map { } }
source.buffer(300,TimeUnit.MILLISECONDS)
.filter{it.size >1}
.map { }
.subscribe {println("双击") }
//结果 输出两次 "双击" 0L, 200L 和 700L, 800L
//可以结合RxBinding使用
button.clicks().buffer(300,TimeUnit.MILLISECONDS)
.filter{it.size >1}
.map { }
.subscribe {println("双击") }
倒计时⭐️ (Riddle101)
Observable.interval(0,1,TimeUnit.SECONDS)
.map { 10-it }
.takeUntil{ it ==0L}
.subscribe(::println)
//结果倒计时 10 9 8 7 6 5 4 3 2 1 0
结尾灵魂拷问❓ : 你真的会RxJava吗? 好像会了一点😙