Как наблюдать за изменениями ViewModel LiveData из класса держателя состояния Compose?

Я следую руководству Android Developers Management State in Compose. https://developer.android.com/jetpack/compose/state#managing-state

Я реализовал свой собственный держатель состояния, который принимает viewModel в качестве параметра, как показано на диаграмме ниже. Внутри держателя состояния у меня есть объекты состояния, такие как mutableStateOf(), которые запускают перекомпоновку.

Проблема, с которой я сталкиваюсь, заключается в том, как MyStateHolder наблюдать за изменениями LiveData в MyViewModel. Поскольку MyStateHolder является POJO, я не могу использовать такие функции, как observeAsState().

Кажется странным, что Google рекомендует этот подход, но не предоставляет готового способа сделать это.

Как я могу наблюдать изменения из viewModel в держателе состояния? Я что-то упускаю?

Jetpack Compose Managing State Architecture

class MyStateHolder(
    private val viewModel: MyViewModel,
) {
    //initialise state variables and observe _portfolioData
    var portfolioDataMap = mutableStateMapOf<String, PortfolioDataModel>().apply {
        putAll(viewModel.portfolioData.value!!)
        viewModel.portfolioData.observeAsState() /*error here: cannot observeAsState in POJO*/
    }
}

class MyViewModel : ViewModel() {
    private val _portfolioData: MutableLiveData<Map<String, PortfolioDataModel>> =
        MutableLiveData()
    val portfolioData: LiveData<Map<String, PortfolioDataModel>>
        get() = _portfolioData

    fun setStateEvent(mainStateEvent: MainStateEvent<String>) {
        //send events to update _portfolioData
    }
}
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
0
10
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для наблюдения за моделью жизни требуется владелец жизненного цикла. Вы можете добавить этот параметр к своему держателю состояния:

class MyStateHolder(
    private val lifecycleOwner: LifecycleOwner,
    private val viewModel: MyViewModel,
) {
    //initialise state variables and observe _portfolioData
    var portfolioDataMap = mutableStateMapOf<String, PortfolioDataModel>().apply {
        putAll(viewModel.portfolioData.value!!)
    }

    init {
        viewModel.portfolioData.observe(lifecycleOwner) {
            portfolioDataMap.clear()
            portfolioDataMap.putAll(it)
        }
    }
}

И во время инициализации вы можете передать его из LocalLifecycleOwner.current, в основном так:

@Composable
fun rememberMyStateHolder() : MyStateHolder {
    val lifecycleOwner = LocalLifecycleOwner.current
    val viewModel = viewModel<MyViewModel>()
    // consider using rememberSaveable instead of remember with a custom saver
    // in case of configuration change, e.g. screen rotation
    return remember(lifecycleOwner, viewModel) {
        MyStateHolder(lifecycleOwner, viewModel)
    }
}

Спасибо, это работает. Похоже, что наблюдатель также помогает инициировать мой пользовательский интерфейс при запуске. Я надеялся, что смогу убрать .apply {putAll(viewModel.portfolioData.value!!)} при объявлении portfolioDataMap, чтобы упростить код. Однако, когда я это делаю, для отображения моего пользовательского интерфейса требуется на пару секунд больше времени. какова будет ваша рекомендация?

mairs8 10.04.2022 20:12

Другие вопросы по теме