android - Kotlin Flow 并行执行两个 API 调用并在每个结果到达时收集它

标签 android kotlin reactive-programming kotlin-coroutines kotlin-flow

我正在尝试使用 Kotlin Flows 为我的 API 调用实现缓存然后网络策略。 这是我现在正在尝试的事情

flowOf(
 remoteDataSource.getDataFromCache() // suspending function returning Flow<Data>
   .catch { error -> Timber.e(error) },
 remoteDataSource.getDataFromServer() // suspending function returning Flow<Data>
).flattenConcat().collect {
  Timber.i("Response Received")
}

这里的问题是 collect 仅在 getDataFromServer 返回时调用。我的期望是我应该从缓存中获取第一个事件,然后在几毫秒后从服务器获取第二个事件。在这种情况下,“Response Received”会打印两次,但会一个接一个地打印。

在另一个变体中,“Response Received” 仅在 getDataFromServer() 返回后打印一次。

 remoteDataSource.getDataFromCache() // suspending function returning Flow<Data>
  .catch { error -> Timber.e(error) }
  .flatMapConcat {
    remoteDataSource.getDataFromServer() // suspending function returning Flow<Data>
  }
  .collect {
    Timber.i("Response Received")
  }

我之前使用过 RxJava 的 Flowable.concat() 并且它工作得很好。 Kotlin Flows 中是否有可以模拟这种行为的东西?

最佳答案

Problem here is collect is only called when getDataFromServer returns.

你的设计中的第一个问题是回流功能也是可暂停的。这是两层可悬浮性。函数应该毫无延迟地返回流,并且流本身应该在传入时发出项目。如果您遵循此准则,您的初始代码就已经可以工作了。

按照你编写这些函数的方式,如果你这样写,它们仍然可以工作:

flow<String> {
    emitAll(getCached())
    emitAll(getFromServer())
}

该语句立即完成,返回冷流。当您对其调用 collect 时,它首先调用 getCached() 并发出缓存值,然后调用 getFromServer() 并发出服务器回应。

<小时/>

上述解决方案仅在您使用缓存值后才启动服务器调用。如果您需要同时激活两个流,请使用 flatMapMerge

假设您解决了上述基本问题并使您的 Flow-returning 函数不暂停,您所需要的就是:

flowOf(getCached(), getFromServer()).flattenMerge()

如果由于某种原因您无法这样做,则必须在每个调用周围添加 emitAll 包装器:

flowOf(
    flow { emitAll(getCached()) }, 
    flow { emitAll(getFromServer()) }
).flattenMerge()

关于android - Kotlin Flow 并行执行两个 API 调用并在每个结果到达时收集它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60194299/

相关文章:

android - MutableSharedFlow - replay 和 extraBufferCapacity 的区别

javascript - 为什么在 Redux-Saga 上使用 Redux-Observable?

system.reactive - 使用Rx运行直方图流

java - HashMap:它在TextView中显示最小值,但min_variable有更多值

android - 在 AsyncTask onPostExecute 中使用 canvas.drawBitmap

kotlin - Kotlin Lambda不在内部调用代码

multithreading - 并行执行计算量大的 map

java - 仅在需要时显示 double 的小数

android - 如何设置按钮不可见android

java - 找到多个文件,操作系统独立路径为 'com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF'