Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深入RxJava之Completable杂记汇总 #148

Open
soapgu opened this issue Jun 10, 2022 · 0 comments
Open

深入RxJava之Completable杂记汇总 #148

soapgu opened this issue Jun 10, 2022 · 0 comments
Labels
JAVA This doesn't seem right ReactiveX ReactiveX

Comments

@soapgu
Copy link
Owner

soapgu commented Jun 10, 2022

  • floatMap和andThen的同与不同

  1. floatMap的替代品andThen

我们知道floatMap是串联Rx对象的“神兵利器”。但是Completable并没有floatMap,因为Completable没有“输出”,所以下游的Rx没有上游的数据。好在有个功能雷同的函数andThen。

  1. 迷惑的andThen
  • 没有变化的本地值
disposables.add(repository.requestLayoutMode(currentMode.getId(), 0)
                    .andThen(repository.requestLayoutContent( siteList))
                    .observeOn(AndroidSchedulers.mainThread())
                    .doOnTerminate(() -> locked = false)
                    .subscribe(() -> MessageHelper.ShowToast(getApplication(), "布局应用成功!"),
                            e -> MessageHelper.ShowToast(getApplication(), String.format("布局应用失败:%s", e.getMessage()))
                    )
            );

比如我有下面两个Completable使用andThen串联
虽然currentMode.getId()是一个本地变量,但是两个Completable的执行的时候,这两个变量“应该”是不一样的。
结果日志打出来getId的值没有改变和相像中的不太一样。

  • 简化demo求证

好吧,我做一个最简物理模型,再次验证

private String myCompleteValue = "no change";
 
  button.setOnClickListener(v ->{
          this.firstTask()
                  .andThen( secondTask() )
                  .subscribe();
      });

 private Completable secondTask(){
      button.setText(  String.format( "Completable %s OK",myCompleteValue) );
      return Completable.complete();
  }

  private Completable firstTask(){
      return Single.timer(1,TimeUnit.SECONDS)
              .flatMapCompletable( t->{
                  this.myCompleteValue = "firstTask complete";
                  return Completable.complete();
              } );
  }

这样验证更简化了,我们直接查看myCompleteValue 的值的变化有没有打印出来就行了。

果然打印出来是no change。

  • 再次反思floatMap和andThen的主要区别

floatMap的参数是一个拉姆达表达式andThen的参数是一个“实体”Completable ,玩过Linq和表达式编译执行都知道,拉姆达表达式是一个“未来式”,他关键是延时执行,只有在第一个Rx对象执行完成后再会执行,而实体Completable 就不是这样了,他会第一时间执行初始化操作。
再次仔细考虑下来,api是完全没有问题的,两个Completable 本身就应该是“独立”的,你本地值改变是你自己整幺蛾子

  • 解决方案
  1. 把secondTask的Completable变成“延时执行”
private Completable secondTask(){
        //button.setText(  String.format( "Completable %s OK",myCompleteValue) );
        //return Completable.complete();
        return Completable.fromAction(()-> button.setText(  String.format( "Completable %s OK",myCompleteValue) ) );
    }
  1. 通过toSingle重新改成floatMap
    这个肯定可行,其实关键还是实际场景还是要和api“匹配”,既然有上下文最好不要用Completable。
    还有如果真的没有上下文使用zip并发更加有效率
  • Completable的并发处理

我们知道一般的Rx并发我们使用zip函数处理

  1. 一号替代函数concatArray
Completable concatArray(@NonNull CompletableSource... sources)

Returns a Completable which completes only when all sources complete, one after another.
看上去匹配度很高
可以并发任意个Completable,很方便。
唯一缺陷是必须是指定已知的参数。对于动态的参数没有办法,类似配置注入式参数就无解

  1. 二号替代函数concat
Completable concat(@NonNull Iterable<@NonNull ? extends CompletableSource> sources)

和下面Single的zip一样是动态的

public static <@NonNull T, @NonNull R> Single<R> zip(@NonNull Iterable<@NonNull ? extends SingleSource<? extends T>> sources,
            @NonNull Function<? super Object[], ? extends R> zipper)

Completable是没有值的,显然要简单多了。

  • 总结

Completable应该算是最简单的Rx对象了。所以在使用上一定要注意“合适”的原则。千万不要把复杂的场景简单化,也不要简单场景复杂化。

@soapgu soapgu changed the title 深入RxJava之Maybe杂记汇总 深入RxJava之Completable杂记汇总 Jun 10, 2022
@soapgu soapgu added JAVA This doesn't seem right ReactiveX ReactiveX labels Jun 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JAVA This doesn't seem right ReactiveX ReactiveX
Projects
None yet
Development

No branches or pull requests

1 participant