Как наблюдать за изменениями 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 в держателе состояния? Я что-то упускаю?

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

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
    }
}
Получение данных из формы с помощью JavaScript - краткое руководство
Получение данных из формы с помощью JavaScript - краткое руководство
Получить данные из формы с помощью JS очень просто: вы запрашиваете элемент формы, передаете его конструктору new FormData() и, наконец, получаете...
Пользовательские правила валидации в Laravel
Пользовательские правила валидации в Laravel
Если вы хотите создать свое собственное правило валидации, Laravel предоставляет возможность сделать это. Создайте правило с помощью следующей...
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
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

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