RxJava用例指南

文章目录

    • 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()
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 { 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> { 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()
 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("bar", "foo").cast(String::class.java)

计数 ⭐️(Riddle 24)

Observable.just(Unit, Unit).count().subscribe(::print) 
//结果 2

默认值 (Riddle 25)

Observable.empty().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 {
      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()
val second = Single.just("Second")
first.switchIfEmpty(second).subscribe(::print) //结果 Second

防抖操作 ⭐️(Riddle36)

val source = PublishSubject.create()
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吗? 好像会了一点

参考

RxRiddles

你可能感兴趣的:(kotlin,android)