то, что я хочу сделать, это получить сетевые данные с помощью firebase AddSnapshotListener, сохранить их в базе данных комнаты и получить данные из базы данных комнаты
так что я сделал это здесь ...
// in dataSource
fun getNetworkData(id : String) = callbackFlow<Data> {
....
streamingApi.get{
trySend(it)
}
...
}
//in repository
fun insertData(id : String) = getNetworkData(id).map{
roomDao.insert(it)
}
fun getRoomData() = roomDao.get()
// viewmodel
viewmodelScope.launch{
repository.insertData(id).collect()
repository.getRoomData().onEach{
updateUi()
...
}
}
а можно ли сразу так собрать?
fun insertAndGet() = flow{
insertData().collect()
getRoomData().collect()
}
и правильно ли собирать поток в репозиторий?
Вы можете использовать слияние для объединения потоков, которые принимают потоки vararg в качестве аргумента.
fun insertAndGet() = merge(insertData(),getRoomdata())
Здесь, если ваши insertData
и getRoomData
имеют поток одного типа,
insertAndGet()
также будет в том же типе. Если они разные, оба будут объединены, но результат объединенного потока будет типа Any
.
Использование:
fun someFun(){
viewModelScope.launch{
insertAndGet().collect{
// You consume the emitted result by using it. And update UI based on the data.
}
}
}
Пожалуйста, обратитесь здесь.
insertData()
немного странно, потому что возвращает поток единиц. Я думаю, что было бы более разумно использовать onEach
вместо map
, чтобы он, по крайней мере, возвращал поток, с которым вы теоретически могли бы что-то делать, кроме как просто передавать данные, а затем отбрасывать их.
Но в любом случае данные будут передаваться из потока getRoomData()
, так что это не имеет большого значения. Если вы объедините их, вы можете просто удалить избыточные данные из потока insertData()
.
На мой взгляд, эти отдельные действия не стоит объединять в единый поток, потому что у них разные обязанности, но я полагаю, вы могли бы сделать следующее. Поскольку два потока выполняются бесконечно, их необходимо собирать параллельно. Этот поток просто собирает поток вставки, поэтому он выполняет свое действие, но не передает значения. Это делается в параллельной дочерней сопрограмме. Данные потока комнаты просто передаются.
fun insertAndGet() = flow {
coroutineScope {
async { insertData().collect() }
emitAll(getRoomData())
}
}
Спасибо!! Это действительно очень помогло
Вы хотите, чтобы база данных вашей комнаты больше не обновлялась, когда вы прекращаете показывать данные в пользовательском интерфейсе?