存储库模式中的 Kotlin Flow

Kotlin Flow in repository pattern

我想将 Flow 作为 return 类型用于我存储库中的所有函数。例如:

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

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

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

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

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

所以他们都是return数据流。如果您对如何实现它有任何想法,我将不胜感激。

------ 更新#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
  }
}

这是一个可行的想法吗?

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

我发现最好(也很容易)的是:

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

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

对于 ex 我有一个在我的项目中获取车辆的存储库(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()
}

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