android 为什么在这段代码中需要flatMapConCat?

eufgjt7s  于 2023-03-11  发布在  Android
关注(0)|答案(1)|浏览(175)

下面是代码:userDao.getUsers从Room数据库返回Flow<List<User>>userService.getUsers从远程服务器返回Flow<List<User>>

class MainViewModel(
    private val userService: UserService,
    private val userDao: UserDao
) : ViewModel() {

    var resultState by mutableStateOf<List<UserEntity>>(emptyList())
        private set

    init {
        viewModelScope.launch {
            flow {
                emit(userService.getUsers())
            }.onEach { userList ->
                val userEntities =
                    userList.map { user ->
                        UserEntity(
                            user.id,
                            user.name, user.username, user.email
                        )
                    }
                userDao.insertUsers(userEntities)
            }.flatMapConcat {
                userDao.getUsers()
            }   .catch { emitAll(userDao.getUsers()) }
                .flowOn(Dispatchers.IO)
                .collect { list ->
                    resultState = list
                }
        }
    }
}

下面我修改了代码,删除了flatMapConcat。为什么?你可能会问。我认为它没有concatinate任何东西,所以我删除了它。现在我有这个代码:

class MainViewModel(
    private val userService: UserService,
    private val userDao: UserDao
) : ViewModel() {

    var resultState by mutableStateOf<List<UserEntity>>(emptyList())
        private set

    init {
        viewModelScope.launch {
            flow {
                emit(userService.getUsers())
            }.onEach { userList ->
                val userEntities =
                    userList.map { user ->
                        UserEntity(
                            user.id,
                            user.name, user.username, user.email
                        )
                    }
                userDao.insertUsers(userEntities)
            }

// flatMapConcat is removed 

                userDao.getUsers()
               .catch { emitAll(userDao.getUsers()) }
                .flowOn(Dispatchers.IO)
                .collect { list ->
                    resultState = list
                }
        }
    }
}

但是,现在resultState不再更新,flow已经用用户填充了数据库,现在我调用userDao.getUsers,这将返回一个Flow。我调用collect来检索一些数据,但总是失败。问题可能是userDao.getUsersflow之前完成,但这些只是普通函数,因此它们必须顺序执行。当我调用userDao.getUsers时,数据库必须填充一些数据。这是事件发生的顺序。请解释一下为什么修改后的代码不起作用。谢谢阅读。

dldeef67

dldeef671#

Kotlin流(通常)为cold
在修改后的代码中,

flow {
    ...
}.onEach {
    ...
}

这只不过是定义了一个冷流。那段代码根本就没有运行。
.flatMapConcat的旧代码将该流与.collect链接在一起,从而使该流运行。
你说的对,你的代码没有任何东西可以连接,.flatMapConcat之前的流只有一个元素。
因此你可以简单地写

val userEntities = userService.getUsers().map {
    ...
}
userDao.insertUsers(userEntities)

userDao.getUsers()
    .retry()
    .collect { list ->
    }

这段代码和你以前的代码有点不同。重试机制不会捕捉userService.getUsers()的异常,我会让你决定这是否重要。
顺便说一句,我相信你不需要.flowOn(Dispatchers.IO),因为Flow-返回房间的方法已经是主要的安全。

相关问题