Android中如何等待void函数执行完成后再触发Completable
问题结论
你当前的实现思路完全无法达到顺序执行的效果,核心问题出在异步流没有做链式串联,且自定义Observable的实现不完整。
现有代码的两个核心错误
- 自定义
observableFoo()只调用了emitter.onNext(),没有调用emitter.onComplete(),这个流永远不会进入终止状态,后续依赖流完成的操作会一直卡住。 onClick()方法中你单独订阅observableFoo()之后,立刻同步执行了someCompletableFunction()。由于observableFoo()被指定在IO线程执行,订阅动作发起后会立刻返回主线程继续往下走,根本不会等待voidFunction执行完成,两个逻辑是完全独立并行的,执行顺序完全不可控。
正确实现方案
你的场景是「先执行一个无返回值的同步/异步操作,完成后再执行下一个Completable任务」,最匹配语义的实现方式是直接用Completable封装void操作,再通过andThen操作符串联两个任务,不需要额外用Observable发射Unit。
第一步:正确封装void函数
用Completable.fromAction直接包裹无返回值函数即可,执行完成后会自动触发onComplete回调,不需要手动处理发射器:
fun completableFoo(): Completable { return Completable.fromAction { voidFunction() } .subscribeOn(Schedulers.io()) }
注意:不要在封装方法里提前写死
observeOn(AndroidSchedulers.mainThread()),把线程切换的控制权留给最终订阅的位置,避免后续串联时出现线程调度混乱。
第二步:串联两个执行流
用andThen操作符把两个任务串成同一个Completable流,它会自动等待上游任务执行完成后,再订阅下游的Completable:
fun onClick(): Completable { return completableFoo() .observeOn(AndroidSchedulers.mainThread()) .doOnComplete { Logger.e("demoApp", "voidFunction执行完成,准备启动Completable任务") } .andThen(someCompletableFunction()) }
额外注意事项
- 如果你坚持要用Observable
的封装方式,记得在 emitter.onNext(Unit)之后必须调用emitter.onComplete(),否则流永远不会终止。但从RxJava的语义设计来说,不需要发射数据、只关心完成/错误状态的任务,优先用Completable,代码可读性更高。 - 所有需要按顺序执行的异步任务,必须通过操作符串联成同一个流,不要分开写多个独立的
subscribe()调用,否则不仅无法保证执行顺序,还容易因为未管理订阅生命周期造成内存泄漏。 - 不要为了等前一个任务完成写线程阻塞代码,会直接卡死对应调度线程,尤其是主线程会触发ANR,直接用框架提供的组合操作符即可,除了
andThen之外,concat、flatMap也可以实现顺序执行,针对Completable场景andThen是最简洁的选择。
内容的提问来源于stack exchange,提问作者moonknight
相关产品推荐
相关产品推荐

