Kotlin Flow.collect выполняется, но не обновляет пользовательский интерфейс onConfigurationChanged

#android #kotlin-coroutines #kotlin-flow

#Android #kotlin-сопрограммы #kotlin-flow

Вопрос:

Я использую Flow для получения данных из Room, затем я вызываю Flow.collect свой класс FragmentLogic. Внутри collect{} я выполняю некоторую работу и обновляю представление через интерфейс ( пример: view.updateAdapter(collectData) ). Это работает нормально, пока onConfigurationChanged не будет вызван an и экран не повернется, код внутри collect выполняется и работает в Logcat, но все, что изменяет пользовательский интерфейс, не работает, функция updateAdapter() вызывается, однако ничего не происходит. Одно из решений, которое я нашел, — это снова вызвать функцию beginObservingProductList() onStart() , если значение savedinstance не равно null, но это создает два экземпляра collect{}, и оба они отображаются в logcat.

Я хочу, чтобы изменения пользовательского интерфейса работали даже после onConfigurationChanged вызова.

Класс Room Dao:

 @Query("SELECT * FROM product")
fun observableList(): Flow<List<ProductEntity>>
  

затем в реализации:

  productDao.observableList().map { collection ->
            collection.map { entity ->
                entity.toProduct
            }
 }.flowOn(DispatchThread.io())
  

И, наконец, я собираю данные и меняю представление:

  private fun beginObservingProductList() = this.launch {
    vModel.liveProductList.map {
        mapToSelectionProduct(it)
 }.collect {
        ui { view.updateAdapter(it) }
        if (it.isNotEmpty()) {
            filledListState()
     } else {
            emptyListState()
     }
        updateCosts()
        vModel.firstTime = false
    }
}
  

Ответ №1:

Поток не поддерживает жизненный цикл, вы должны использовать LiveData для обработки изменений конфигурации.

Чтобы использовать LiveData с потоком, реализуйте androidx.lifecycle:lifecycle-livedata-ktx:2.2.0 , затем вы можете использовать .asLiveData() расширение func .

Репозиторий

 fun getList()= productDao.observableList().map { collection ->
        collection.map { entity ->
            entity.toProduct
        }
}.flowOn(DispatchThread.io())
  

ViewModel

 val liveData = repository.getList().asLiveData()
  

Активность / Фрагмент

  viewModel.liveData.observe(this,Observer{ list->

//do your thing
})