Реализация MVVM в Jetpack Compose и сравнение ViewModel и запоминание
Реализация MVVM в Jetpack Compose и сравнение ViewModel и запоминание

Предисловие

ViewModel и remember да Jetpack Compose Два разных механизма управления данными в формате .

Они имеют следующие различия:

управление жизненным циклом:

  • ViewModel: ViewModel даA добрый для хранения и управления данными, связанными с интерфейсом, которые жизненно важны цикл, связанный с ViewModelStoreOwner связанный (обычно да Activity или Fragment)。 это означает ViewModel вданные будут в ассоциированном ViewModelStoreOwner Поддерживать состояние в присутствии до тех пор, пока не наступит их жизненный цикл окончен.
  • remember: remember да А используется для хранения эфемерных данных Compose Государственный менеджер. 它的жизненный циклс вызовом этогокомпонентысвязанный,Обычно компоненты функционируют. Когда компоненты воссоздаются,remember данные, хранящиеся в нем, будут потеряны.

Обмен данными:

  • ViewModel: ViewModel Обычно используется для хранения данных персистентности, связанных с интерфейсом, которые могут совместно использоваться несколькими компонентами, например, в пределах одного и того же компонента. Activity разница в Fragment распределяется между данными.
  • remember: remember В основном используется для хранения временного локального состояния, например UI статус, временный кэш и т. д. Его область действия обычно ограничивается вызывающей стороной.

Сохранение данных:

  • ViewModel: ViewModel вданные обычно имеют более продолжительный жизненный характер цикл и сохраняется при изменении конфигурации (например, при повороте экрана).
  • remember: remember вданные Обычно временные и не сохраняются при изменении конфигурации.

использование:

  • ViewModel: обычно проходил в Activity или Fragment серединаиспользовать ViewModelProvider получать ViewModel экземпляр и наблюдать при необходимости ViewModel в LiveData илииспользоватьэто обеспечиваетданные。
  • remember: remember Вы можете напрямую Compose компонентывнутреннийиспользовать,Позвонив remember { } или rememberSaveable { } для создания и хранения состояния.

Общий:

  • ViewModel Подходит для управления сохранением данных в различных компонентах распределения. между данными.
  • remember подходит для управления кратковременными UI Штат и местный штат.

remember/rememberSaveable

В создании,rememberиrememberSaveableВседа Метод сохранения состояния компонуемых функций,Но они различаются тем, как сохраняется состояние и при каких обстоятельствах оно пересчитывается.

remember: Эта функция является частью комбинированной функции. цикл всегда остается неизменным. это Это означает, что каждый раз, когда функция композиции вызывается снова, она будет использовать ранее сохраненное значение состояния без его пересчета. Это полезно для статических файлов, которые не изменяются при взаимодействии с пользователем. Если изменение статуса не требуется в компонентахжизненный Стойкость вне цикла,rememberда Более легкий вариант。

Язык кода:javascript
копировать
var password by remember { mutableStateOf("") }

rememberSaveable: Эта функция также сохраняет состояние, но также сохраняет его, чтобы его можно было восстановить после того, как приложение перейдет в фоновый режим и будет уничтожено. Это полезно для приложений, требующих изменения конфигурации (например, поворота экрана). циклстатус очень полезен。Это спасет государство вBundleсередина,обеспечить устойчивость государства.

Язык кода:javascript
копировать
var password by rememberSaveable { mutableStateOf("") }

поэтому,rememberSaveableОбеспечивает постоянную поддержку состояния,иrememberтогда только вкомпонентыжизненный Сохраните состояние в цикле.

Какой из них выбрать, зависит от того, какое состояние вам нужно — нужно ли оно сохраняться при перезапуске приложения.

mutableStateOf/mutableStateListOf

mutableStateOf да Jetpack Compose Функция в , используемая для создания изменяемого состояния.

Его роль – создать состояние, которое можно изменить.,И когда статус когда изменится,Compose будет пересчитан и обновлен UI。

Конкретно,mutableStateOf Функция принимает начальное значение в качестве параметра и возвращает MutableState объект.

MutableState Объект имеет value Атрибуты могут читать и изменять значение этого состояния.

когда MutableState Когда значение объекта изменится, Compose будет пересчитан в зависимости от нового статуса Пользовательский интерфейс для обеспечения UI Отразить последний статус.

Например, предположим, что у нас есть mutableStateOf Объект для представления значения счетчика:

Язык кода:javascript
копировать
val countState = remember { mutableStateOf(0) }

Затем мы можем изменить его, изменив countState.value Значение для обновления состояния счетчика:

Язык кода:javascript
копировать
countState.value += 1

Каждыйкогда countState.value Когда значение изменяется, значение, связанное со статусом UI Оно будет пересчитано и обновлено, чтобы отразить последнее значение счетчика.

Общий:

mutableStateOf Роль да в Jetpack Compose Создайте в нем изменяемое состояние, чтобы его можно было динамически обновлять. UI и убедитесь, что UI Отражает последнее значение статуса.

ViewModel

Класс ViewModelдабизнес-логикаили Контейнер состояний уровня экрана。Он используется для предоставления состояния интерфейсу.,И инкапсулируйте связанную бизнес-логику.

Его главное преимущество заключается в том, что он может кэшировать состояние и сохранять его после изменений конфигурации. это означаетсуществовать activity Интерфейсу не потребуется повторно получать данные при переходе между пользовательскими интерфейсами или после внесения изменений в конфигурацию (например, при повороте экрана).

Добавить курс

Язык кода:javascript
копировать
class MyViewModel : ViewModel() {
    val listItems by mutableStateOf(listOf("Чжан Сан", «Ли Си»,«Ван Ву»))
}

На данный момент мы будем создавать новый объект каждый раз, когда его инициализируем.

Язык кода:javascript
копировать
val mainViewModel:MyViewModel = MyViewModel()
Log.i("ZLog","Код объекта:"+mainViewModel.hashCode())

Таким образом, неудобно повторно использовать настроенные компонентыиспользованные.,можешь ли ты позволить намViewModel的实例существоватьодиндобрыйсерединада Тот же экземпляр?

да Да.

Добавить цитату

Язык кода:javascript
копировать
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")

На данный момент мы пишем так, когда используем экземпляр

Язык кода:javascript
копировать
val mainViewModel:MyViewModel = viewModel()
Log.i("ZLog","Код объекта:"+mainViewModel.hashCode())

Уведомление :

viewModel()Метод будет основан надобрыйформаи所существовать的ViewModelStoreOwnerСоздается автоматическииэкземпляр кэша。 viewModel Примеры из литературы ViewModelStoreOwner(в целомдаодин Activity или Fragment)связанный的,это означает ViewModel жизненный цикл и его ViewModelStoreOwner дамматчи.

Пример списка

ViewModel

Язык кода:javascript
копировать
class MyViewModel : ViewModel() {
    val listItems = mutableStateListOf<String>()
    fun loadMore(){
        Log.i("ZLog","добавить вданные")        listItems.add((Math.random()*100).toString())
    }
}

Также возможна инициализация данных

Язык кода:javascript
копировать
val listItems = mutableStateListOf("Чжан Сан","Ли Си»,«Ван Ву»)

компоненты

Язык кода:javascript
копировать
@Composable
fun MyList(mList: List<String>) {
    SideEffect {
        Log.i("ZLog","SideEffect")
    }
    LazyColumn {
        items(mList.size) {
            ListItem(mList[it])
        }
    }
}

@Composable
fun ListItem(text: String) {
    // Создание элементов списка UI
    Text(text = text)
}

данныепри обновленииSideEffectне вызвало。

SideEffect Функция обратного вызова есть только в MyList Компонент вызывается при его первом создании, потому что SideEffect Будет запускать свой блок кода при создании компонентов и каждый раз при повторной сборке компонентов.

Но да в этом случае,MyList компонентысуществовать mList Он не перегруппировывается при изменении, потому что Compose Не удалось обнаружить изменения в данных списка.

сделать SideEffect Вызывается при изменении данных списка, вы можете рассматривать данные списка как key Параметры, переданные в MyList компоненты,Когда данные списка «Когда» меняются вот так,MyList компоненты будут воссозданы, вызывая SideEffect функция обратного вызова.

Например:

Язык кода:javascript
копировать
@Composable
fun MyList(mList: List<String>, key: Any = mList) {
    SideEffect {
        Log.i("ZLog","SideEffect")
    }
    LazyColumn {
        items(mList.size) {
            ListItem(mList[it])
        }
    }
}

После этой модификации MyList В, мы используем key Параметры будут перечисленыданныеперешел ккомпоненты。так,Когда данные списка меняются,key Значение также изменится, что приведет к срабатыванию MyList рекомбинация, так что SideEffect может быть выполнено снова.

использовать

Язык кода:javascript
копировать
Box() {
    val mainViewModel: MyViewModel = viewModel()
    MyList(mainViewModel.listItems)
    Button(modifier=Modifier.align(Alignment.BottomEnd).padding(10.dp),onClick = {
        mainViewModel.loadMore()
    }) {
        Text("нагрузкаданные")    }
}

Уведомление

Данные в ViewModel должны быть обновлены в потоке пользовательского интерфейса до начала обновления страницы.

Распространенные ошибки

Запрос интерфейса

Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied

возобновлятьданныесуществоватьLaunchedEffect

Язык кода:javascript
копировать
val appViewModel: AppViewModel = viewModel()
LaunchedEffect(Unit){
    appViewModel.loadInit()
}
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose