RxJava:首个Observable就绪后在主线程操作并返回原流的方法
解决方案
首先修正你代码里的一个问题:Observable.just(myservice.getNewsArticles())会同步执行网络请求,阻塞当前线程,正确的做法是用Observable.fromCallable包装,让请求在指定线程异步执行。
针对你的需求——ob1完成后立即更新UI,同时让ob2后台执行,且整个链式返回ob1的流——可以通过以下两种方式实现:
方式一:利用doOnNext触发副作用(推荐)
在ob1的流中,用doOnNext完成UI更新,同时在该回调里独立触发ob2的请求,不干扰主流程的返回值:
// 正确创建ob1,让网络请求在IO线程异步执行 val ob1 = Observable.fromCallable { myservice.getNewsArticles() } .subscribeOn(Schedulers.io()) ob1 // 切到主线程更新UI .observeOn(AndroidSchedulers.mainThread()) .doOnNext { newsArticle -> // 立即更新新闻UI updateNewsUI(newsArticle) // 独立触发ob2的请求,后台执行不阻塞主流程 Observable.fromCallable { myservice.getCelebrityNamesFromArticle(newsArticle.id) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { celebrityNames -> // 拿到名人数据后更新对应UI updateCelebrityUI(celebrityNames) }, { error -> // 处理ob2请求失败的情况 handleOb2Error(error) } ) } // 主订阅最终拿到的是ob1的新闻数据 .observeOn(AndroidSchedulers.mainThread()) .subscribe( { newsArticle -> // 这里可以做ob1数据的后续处理 }, { error -> // 处理ob1请求失败的情况 handleOb1Error(error) } )
方式二:用flatMap保持主流程返回ob1数据
如果一定要用flatMap,可以在映射函数里触发ob2请求,同时返回ob1的原数据:
val ob1 = Observable.fromCallable { myservice.getNewsArticles() } .subscribeOn(Schedulers.io()) ob1 .observeOn(AndroidSchedulers.mainThread()) .doOnNext { newsArticle -> // 立即更新新闻UI updateNewsUI(newsArticle) } // 切回IO线程处理ob2请求 .observeOn(Schedulers.io()) .flatMap { newsArticle -> // 触发ob2请求,后台执行 myservice.getCelebrityNamesFromArticle(newsArticle.id) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { celebrityNames -> updateCelebrityUI(celebrityNames) }, { error -> handleOb2Error(error) } ) // 返回ob1的原数据,让主流程继续传递它 Observable.just(newsArticle) } .observeOn(AndroidSchedulers.mainThread()) .subscribe( { newsArticle -> /* 主订阅拿到ob1数据 */ }, { error -> handleOb1Error(error) } )
关于你提到的flatMap双函数映射器
你说的flatMap双函数重载是flatMap(onNextMapper, onErrorMapper),第二个函数是用来处理错误事件的映射,不是用来同时返回两个流的,所以它解决不了你的问题,不用在这上面浪费精力。
内容的提问来源于stack exchange,提问作者j2emanue
相关产品推荐
相关产品推荐

