您认为实现返回流的用例/存储库的正确方法是什么(单一事实来源 + 远程获取)

What would you consider the correct way to implement Use Cases/Repositories that return a Flow (Single Source of Truth + remote fetching)

提问人:Augusto Carmo 提问时间:7/20/2023 更新时间:7/20/2023 访问量:29

问:

假设我有以下用例将用户作为流获取

class FetchUsersFlowUseCase(
    private val userRepository: UserRepository
) {

    operator fun invoke(): Flow<List<User>> {
        return userRepository.fetchUsersFlow()
    }
}

以及一个具有将用户作为 Flow 获取函数的存储库。调用该函数时,还会尝试同步本地数据库(即单一事实来源)。

class UserRepositoryImpl(
    private val localUserDataSource: LocalUserDatasource,
    private val remoteUserDataSource: RemoteUserDatasource,
    private val coroutineScope: CoroutineScope
) : UserRepository {

    override fun fetchUsersFlow(): Flow<List<User>> {
        coroutineScope.launch {
            val remoteUsersResult = remoteUserDataSource.fetchUsers()
            if (remoteUsersResult.isSuccess) {
                // Success: update users locally
            } else {
                // What to do? 
                // How to correctly notify who observes that something wrong happened?
            }
        }

        return localUserDataSource.fetchUsersFlow()
    }
}

但是,如果发生意外情况(例如:没有 Internet 连接),我该如何正确通知谁观察了 Flow?

Android Kotlin Clean-Architecture Kotlin-Flow 用例

评论

0赞 Mohammad Reza Khahani 7/20/2023
查看这篇中篇文章:使用密封类和协程对改造响应进行建模

答:

0赞 Jorn 7/20/2023 #1

将结果包装在一个对象中,以便使用者可以确定成功:

sealed interface Result {
  object Error: Result
  data class Success(val value: List<User>)
}

    override fun fetchUsersFlow(): Flow<Result> {
        coroutineScope.launch {
            val remoteUsersResult = remoteUserDataSource.fetchUsers()
            if (remoteUsersResult.isSuccess) {
                yourFlow.emit(Result.Success(remoteUsersResult))
            } else {
                yourFlow.emit(Result.Error)
            }
        }

        return localUserDataSource.fetchUsersFlow()
    }

那么在消费者方面,你可以

when(valueFromFlow) {
  Result.Error -> // handle it
  is Result.Success -> it.value // is your List<User>
}

您可以添加更多实现来表示其他情况,或者也可以创建一个数据类并为其提供包含详细信息的字段。ResultError

评论

0赞 Augusto Carmo 7/20/2023
您将如何与?它们目前不一样。yourFlowreturn localUserDataSource.fetchUsersFlow()
0赞 Jorn 7/20/2023
localUserDataSource.fetchUsersFlow()是来源吗?然后,在该流上使用 ,而不是 ,并且只是一个 .coroutineScope.launch.collectyourFlowMutableStateFlow()
0赞 Augusto Carmo 7/20/2023
你能用那个代码修复来编辑你的答案吗?非常感谢:)
0赞 Jorn 7/20/2023
我完全不确定这是你想要的。哪个流是源?是否要合并来自本地和远程源的数据?还是您进入本地流程?最后一个选项感觉很奇怪。emit