使用 Dao 和通用结果的协程流 class

Coroutines Flow with Dao and generic Result class

我有一个 Dao class,其中 returns 汽车对象列表作为流。

@Query("SELECT * FROM Car")
fun getAllCars(): Flow<List<Car>>

在我的仓库中,我可以按如下方式使用这个 Dao

fun getAllCars(): Flow<List<Car>>
//Implementation
override fun getAllCars() = carDao.getAllCars()

我可以在视图模型中观察到这个 flow,一切正常,生活很好。

现在,在阅读 Developer Android site 上关于

的 post 之后

包含有关加载此数据的数据和状态的通用 class。

我受到了启发,所以我又读了一篇 post here,其中讨论了如何获得结果 class。

所以,我对存储库做了一些更改,但我无法解决它们。

错误:


suspend fun getSomeData(): Flow<Result<List<Car>>> {
        carDao.getAllCars().collect {
            if (it.isNotEmpty()) {
                return flowOf(Result.Success(it))  //<-- Here I am getting error from IDE
            }
            else {
                val throwable = Throwable()
                return flowOf(Result.Failure<List<Car>>(throwable)) //<-- Here I am getting error from IDE
            }
        }
    }

错误是Return is not allowed hereChange to 'return@Collect'

我要实现的是:

// At view model side
viewmodelScope.launch {

    repo.getSomeData().collect {
      if (it == Result.Success) {
        //Show data
      }
      else {
        //Show empty screen
      }

    }
}

是不是我实现Result的方式不对?我无法弄清楚出了什么问题。为什么我不能 return 流出流

如果你想使用 Result,你应该 returnResult 。它看起来像这样:

        suspend fun getSomeData(): Result<Flow<List<Car>>> {
            return  carDao.getAllCars().collect {
                if (it.isNotEmpty()) {
                   Result.Success(flowOf(it)) 
                } else {
                   Result.Failure(Throwable())) 
                }
             }
        }

这就是您的函数的外观。请注意,它不需要是 suspend fun.

fun getSomeData(): Flow<Result<List<Car>>> = flow {
    carDao.getAllCars().collect {
        if (it.isNotEmpty()) {
            emit(Result.Success(it))
        }
        else {
            emit(Result.Failure<List<Car>>(Throwable()))
        }
    }
}

但是它的作用无非是增加了一个映射步骤,可以泛化。

fun <T> Flow<List<T>>.toResultFlow(): Flow<Result<List<T>>> = this.map {
    if (it.isNotEmpty()) Result.Success(it)
    else Result.Failure(Throwable())
}