如果 Maybe 完成,则从另一个来源将 Maybe 转换为 Single

Convert Maybe to Single from another source if Maybe completes

我想构建一个 Repository class 那个 returns 一个 Single<Something>.

class 应该首先查看 Cache 其中 returns Maybe<Something> 如果 Maybe 完成,请转到我的 Service returns Single<Something>

interface Cache {
    fun getSomething(): Maybe<Something>   
}

interface Service {
    fun getSomething(): Single<Something>   
}

class Repository (
    private val cache: Cache,
    private val service: Service
) {

    fun getSomething(): Single<Something> {
      return cache.getSomething()
               .????(feed.getSomething()) //onCompleteTransformToSingle() or similar
    }
}    

我已经搜索过 JavaDoc,但似乎不存在适用于这种情况的转换器。

有什么好的处理方法吗?

当您需要使用元数据执行 RxJava 操作时(没有缓存结果),您可能必须使用 materialize().

将您的观察者链转换为元数据流

(抱歉我的 Kotlin 不够流利)

fun getSomething(): Single<Something> {
  return cache.getSomething()
    .toObservable()
    .materialize()
    .take(1)
    .flatMap( it.hasValue() ? Single.just( it.getValue() )
              : Single.fromCallable( apiCall() )
      );
}

materialize() 运算符将观察者流转换为 Notification 的流。然后您可以检查第一个通知,如果它有值,就使用它。否则,请拨打您的网络电话。

您可以使用以下两个相当简单的选项。我发现第一个更明确。第二个好处是您可以在缓存中出现任何错误时调用网络。

这些假定 Maybe 是从缓存中 return 编辑的。例如,如果在缓存中没有找到值,return Maybe.empty()

1) 如果流中有空值,switchIfEmpty() 将使用调用网络的备用可观察对象。如果流中没有空值,网络将永远不会被调用。

override fun getSomething(): Single<Something> {
      return cache.getSomething()
        .switchIfEmpty(
          Maybe.defer {
            feed.getSomething().toMaybe()
          }
        )
        .toSingle()
  }

2) 空值可能会 return 转换为 Single() 时出错,触发网络调用。

override fun getSomething(): Single<Something> {
      return cache.getSomething()
        .toSingle()
        .onErrorResumeNext {
           feed.getSomething()
        }
  }

使用以下带有 3 个参数的 flatMap 调用 Maybe

public final <R> Maybe<R> flatMap(
        Function<? super T, ? extends MaybeSource<? extends R>> onSuccessMapper,
        Function<? super Throwable, ? extends MaybeSource<? extends R>> onErrorMapper,
        Callable<? extends MaybeSource<? extends R>> onCompleteSupplier)

例子

class Repository (
    private val cache: Cache,
    private val service: Service
) {

    fun getSomething(): Single<Something> {
      return cache.getSomething()
                .flatMap(
                    Function {
                        Single.just(it) // onSuccess
                    },
                    Function {
                        Single.error(it) // onError
                    },
                    Callable {
                        feed.getSomething() // onComplete
                    }
                
    }

或者

class Repository (
    private val cache: Cache,
    private val service: Service
) {

    fun getSomething(): Single<Something> {
      return cache.getSomething()
                .flatMap(
                    {
                        Single.just<Something>(it) // onSuccess
                    },
                    {
                        Single.error(it) // onError
                    },
                    {
                        feed.getSomething() // onComplete
                    }
                
    }
}