1

我想使用 Flow 作为存储库中所有函数的返回类型。例如:

suspend fun create(item:T): Flow<Result<T>> 

此函数应调用 2 个数据源:远程(将数据保存在服务器上)和本地(将服务器返回的数据保存在本地)。问题是我如何实现这个场景:

  1. 尝试使用 RemoteDataSource 保存数据
  2. 如果 1. 失败 - 尝试 N 次 M 超时
  3. 如果数据最终从服务器返回 - 在本地与 LocalDataSource 相同
  4. 使用本地保存的数据返回流

RemoteDataSource 和 LocalDataSource 都有create相同的签名:

suspend fun create(item:T): Flow<Result<T>> 

所以它们都返回数据流。如果您对如何实施它有任何想法,我将不胜感激。

------ 更新 #1 ------

可能解决方案的一部分:

suspend fun create(item:T): Flow<T> {
 // save item remotely
 return remoteDataSource.create(item)
  // todo: call retry if fails
  // save to local a merge two flows in one
  .flatMapConcat { remoteData ->
   localDataSource.create(remoteData)
  }
  .map {
   // other mapping
  }
}

这是一个可行的想法吗?

4

1 回答 1

1

我认为您的想法是正确的,但您正试图一次完成所有事情。

我发现最好(并且很容易)的方法是:

  • 来自本地数据源的暴露数据流(使用 Room 很容易)

  • 一个或多个公开的挂起函数,如createrefresh对远程数据源进行操作并保存到本地(如果没有错误)

例如,我有一个在我的项目中获取车辆的存储库(isCurrent信息只是本地的,并且isLeft/isRight是因为我使用Either但任何错误处理都适用):

class VehicleRepositoryImpl(
    private val localDataSource: LocalVehiclesDataSource,
    private val remoteDataSource: RemoteVehiclesDataSource
) : VehicleRepository {

    override val vehiclesFlow = localDataSource.vehicleListFlow
    override val currentVehicleFlow = localDataSource.currentVehicleFLow

    override suspend fun refresh() {
        remoteDataSource.getVehicles()
            .fold(
                ifLeft = { /* handle errors, retry, ... */ },
                ifRight = { reset(it) }
            )
    }

    private suspend fun reset(vehicles: List<VehicleEntity>) {
        val current = currentVehicleFlow.first()
        localDataSource.reset(vehicles)
        if (current != null) localDataSource.setCurrentVehicle(current)
    }

    override suspend fun setCurrentVehicle(vehicle: VehicleEntity) =
        localDataSource.setCurrentVehicle(vehicle)

    override suspend fun clear() = localDataSource.clear()
}

希望这会有所帮助,您可以根据自己的情况进行调整:)

于 2020-07-01T13:49:57.987 回答