RxJava Observable.create包装可观察的订阅

时间:2017-06-12 15:23:27

标签: android rx-java kotlin rx-java2

我使用了Observable.create,因此我可以在某些数据可用时通知订阅者。我有点不确定在我的create方法中订阅了observable。这些嵌套订阅是否会给我带来任何问题?我并不完全熟悉使用Observable.create创建observable,所以我想确保我没有做任何不寻常的事情或滥用它。提前谢谢!

abstract class NetworkResource<ApiType, DbType> constructor(private val schedulerProvider: SchedulerProvider) {

    abstract fun fetchFromApi(): Single<ApiType>
    abstract fun fetchFromDb(): Observable<Optional<DbType>>
    abstract fun saveToDb(apiType: ApiType?)
    abstract fun shouldFetchFromApi(cache: DbType?): Boolean

    fun fetch(): Observable<Optional<DbType>>  {
        return Observable.create<Optional<DbType>> {
            val subscriber = it

            fetchFromDb()
                    .subscribe({
                        subscriber.onNext(it)

                        if(shouldFetchFromApi(it.get())) {
                            fetchFromApi()
                                    .observeOn(schedulerProvider.io())
                                    .map {
                                        saveToDb(it)
                                        it
                                    }
                                    .observeOn(schedulerProvider.ui())
                                    .flatMapObservable {
                                        fetchFromDb()
                                    }
                                    .subscribe({
                                        subscriber.onNext(it)
                                        subscriber.onComplete()
                                    })
                        }
                        else {
                            subscriber.onComplete()
                        }
                    })

        }
    }
}

1 个答案:

答案 0 :(得分:2)

是的,这会导致问题。

首先,像这样嵌套Observable并不是惯用的,Reactive方法的优势之一就是组成Observables,因此只有一个干净的流。通过这种方式,你正在破坏链,最直接的结果是更难以阅读的交织代码,以及更多代码来连接通知事件,基本上就像用Observable包装异步回调方法一样。 /> 在这里,因为你已经有了反应组件,你可以简单地组成它们而不是用回调方法处理它们。

其次,由于打破链条,最严重且最直接的链接 - 取消订阅外部Observable不会自动影响内部Observable。同样适用于尝试添加subscribeOn()和不同的情况,其中背压很重要,它也适用。

作曲替代方案可能是这样的:

fun fetch2(): Observable<Optional<DbType>> {
        return fetchFromDb()
                .flatMap {
                    if (shouldFetchFromApi(it.get())) {
                        fetchFromApi()
                                .observeOn(schedulerProvider.io())
                                .doOnSuccess { saveToDb(it) }
                                .observeOn(schedulerProvider.ui())
                                .flatMapObservable {
                                    fetchFromDb()
                                }

                    } else {
                        Observable.empty()
                    }
                }
    }

如果出于某种原因,您希望在任何情况下单独发出第一个fetchFromDb()结果,您也可以使用带有选择器的publish()来执行此操作:

 fun fetch2(): Observable<Optional<DbType>> {
    return fetchFromDb()
            .publish {
                Observable.merge(it,
                        it.flatMap {
                            if (shouldFetchFromApi(it.get())) {
                                fetchFromApi()
                                        .observeOn(schedulerProvider.io())
                                        .doOnSuccess { saveToDb(it) }
                                        .observeOn(schedulerProvider.ui())
                                        .flatMapObservable {
                                            fetchFromDb()
                                        }

                            } else {
                                Observable.empty()
                            }
                        })
            }

}