Что-то побудило меня написать статью про эту новую фичу. Погуглив пару секунд я наткнулся на замечательную статью на Medium'e, пример который я привожу тут взят оттуда, только с небольшим моим дополнением, а так по сути это реплика статьи с Medium'a…
Часто бывает когда сталкиваешься с проблемой поворота экрана, данные просто теряются при обновлении активити, и приходится или вызывать снова запрос на получение или сохранять эти данные в onSaveInstanceState().
ViewModel же помогает сохранять инстанс любого объекта который вы имеете, пусть то будет модель какого-то респонса с сервера, или на пример модель в которой хранятся локальные данные для текущей активити. При повороте экрана да и вообще на протяжении всего жизненого цикла приложения данная информация будет жить пока вы не закроете приложение вообще.
Что бывает если мы не сохраняем инстанс переменной в onSaveInstanceState() или во ViewModel? Вот вам пример.
При обновлении активити когда экран поворачивается мы теряем наши данные, и так будет пока мы не сделаем переопределение этой переменной в onSaveInstanceState(). Вот пример кода который показан на этой гифке.
MainActivity.java
То есть, просто ничего ни где не сохраняется, ничто нигде не записывается, просто есть переменная counterA, которую мы увеличиваем по нажатию кнопки и все. При повороте экрана она просто теряет свой инстанс и пересоздается заново. Для того что бы она у нас записывалась и хранилась пока живо приложение — нам нужно создать класс — модель который будет наследоваться от ViewModel и будет хранить в себе переменные которые мы хотим запомнить. То есть вынести всю логику работы с переменные в отдельный класс что бы он не затрагивал UI.
ScoreViewModel.java
Тут я создал две переменные для хранения данных, их тут можно написать сколько угодно, разных типов и оно все будет сохраняться, для примера будет просто две простые переменные типа int. И этот класс унаследован от ViewModel который собственно и указывает на то что мы в дальнейшем сможем использовать для нашей магии по сохранению данных.
Вот мы создали значит свою модель и унаследовали ее от ViewModel, вписали туда все нужные параметры, а что же дальше делать? А дальше нам нужно подключить провайдера который будет хранить инстанс данной модели в активити или фрагменте который мы передадим ему как контекст.
<THIS ARGUMENT> — это или this или getActivity() или какой-либо context UI класса.
ScoreViewModel.class — собственно наш класс — модель который мы создали для хранения, он может называться если что — как угодно.
Дальше нам нужно подключить две библиотеки для того что бы работать с данными провайдером, так как он не идет в стандартной сборке SDK.
app/build.gradle
Для пример я привел все библиотеки что у меня тут есть, но нам важны две либы по центру, а именно lifecycle:extensions и lifecycle:viewmodel. Они обе нужны для того что бы использовать нужные классы для реализации (алгоритма или паттерна — как оно там у них называется без понятия) ViewModel. Так же у нас там как всегда ButterKnife и Appcompat для подключения вьюх и работы со стилями Compat.
activity_main.xml
Это не столь важный момент но для полной картинки он нужен, у нас тут две кнопки и две текствьюхи расположеные друг рядом с другом. По нажатию на одну и вторую кнопки у нас будут увеличиваться каунтеры над ними.
MainActivity.java
Собственно к коду выше я добавил новую переменную ScoreViewModel которая является инстансом нашей модели, и в onCreate() я создал при помощи провайдера ViewModelProviders ее инстанс который теперь будет хранить все что мы будем в нее записывать. Дальше по нажатию на onButtonBClick() у нас будет производиться запись инстанса mViewModel.scoreTeamB увеличеный на 1. И так же в onCreate() мы достаем его и отображаем в displayForTeamB().
И теперь эффект получается такой что слева у нас хранится инстанс который создается в UI и он не сохраняется, а с права у нас хранится инстанс ScoreViewModel и каждый раз при перевороте оно не создает новый инстанс этой переменной, а просто достает из закрамов последний сохраненный вариант этого объекта.
Вот собственно и вся магия. Для примера это очень простой и классный вариант. Если усложнить то можно попробовать создать запрос на пример к серверу, и потом сохранять инстанс респонса в ViewModel и пользоваться им в дальнейших работах на экране. В общем это крутая штука, советую использовать вам в своих проектах.
Исходники:
GitHub
Часто бывает когда сталкиваешься с проблемой поворота экрана, данные просто теряются при обновлении активити, и приходится или вызывать снова запрос на получение или сохранять эти данные в onSaveInstanceState().
ViewModel же помогает сохранять инстанс любого объекта который вы имеете, пусть то будет модель какого-то респонса с сервера, или на пример модель в которой хранятся локальные данные для текущей активити. При повороте экрана да и вообще на протяжении всего жизненого цикла приложения данная информация будет жить пока вы не закроете приложение вообще.
Что бывает если мы не сохраняем инстанс переменной в onSaveInstanceState() или во ViewModel? Вот вам пример.
![image](https://github.com/dajver/ViewModelExample/blob/master/imgs/image1.gif?raw=true)
При обновлении активити когда экран поворачивается мы теряем наши данные, и так будет пока мы не сделаем переопределение этой переменной в onSaveInstanceState(). Вот пример кода который показан на этой гифке.
MainActivity.java
То есть, просто ничего ни где не сохраняется, ничто нигде не записывается, просто есть переменная counterA, которую мы увеличиваем по нажатию кнопки и все. При повороте экрана она просто теряет свой инстанс и пересоздается заново. Для того что бы она у нас записывалась и хранилась пока живо приложение — нам нужно создать класс — модель который будет наследоваться от ViewModel и будет хранить в себе переменные которые мы хотим запомнить. То есть вынести всю логику работы с переменные в отдельный класс что бы он не затрагивал UI.
ScoreViewModel.java
Тут я создал две переменные для хранения данных, их тут можно написать сколько угодно, разных типов и оно все будет сохраняться, для примера будет просто две простые переменные типа int. И этот класс унаследован от ViewModel который собственно и указывает на то что мы в дальнейшем сможем использовать для нашей магии по сохранению данных.
Вот мы создали значит свою модель и унаследовали ее от ViewModel, вписали туда все нужные параметры, а что же дальше делать? А дальше нам нужно подключить провайдера который будет хранить инстанс данной модели в активити или фрагменте который мы передадим ему как контекст.
<THIS ARGUMENT> — это или this или getActivity() или какой-либо context UI класса.
ScoreViewModel.class — собственно наш класс — модель который мы создали для хранения, он может называться если что — как угодно.
Дальше нам нужно подключить две библиотеки для того что бы работать с данными провайдером, так как он не идет в стандартной сборке SDK.
app/build.gradle
Для пример я привел все библиотеки что у меня тут есть, но нам важны две либы по центру, а именно lifecycle:extensions и lifecycle:viewmodel. Они обе нужны для того что бы использовать нужные классы для реализации (алгоритма или паттерна — как оно там у них называется без понятия) ViewModel. Так же у нас там как всегда ButterKnife и Appcompat для подключения вьюх и работы со стилями Compat.
activity_main.xml
Это не столь важный момент но для полной картинки он нужен, у нас тут две кнопки и две текствьюхи расположеные друг рядом с другом. По нажатию на одну и вторую кнопки у нас будут увеличиваться каунтеры над ними.
MainActivity.java
Собственно к коду выше я добавил новую переменную ScoreViewModel которая является инстансом нашей модели, и в onCreate() я создал при помощи провайдера ViewModelProviders ее инстанс который теперь будет хранить все что мы будем в нее записывать. Дальше по нажатию на onButtonBClick() у нас будет производиться запись инстанса mViewModel.scoreTeamB увеличеный на 1. И так же в onCreate() мы достаем его и отображаем в displayForTeamB().
И теперь эффект получается такой что слева у нас хранится инстанс который создается в UI и он не сохраняется, а с права у нас хранится инстанс ScoreViewModel и каждый раз при перевороте оно не создает новый инстанс этой переменной, а просто достает из закрамов последний сохраненный вариант этого объекта.
![image](https://github.com/dajver/ViewModelExample/blob/master/imgs/image2.gif?raw=true)
Вот собственно и вся магия. Для примера это очень простой и классный вариант. Если усложнить то можно попробовать создать запрос на пример к серверу, и потом сохранять инстанс респонса в ViewModel и пользоваться им в дальнейших работах на экране. В общем это крутая штука, советую использовать вам в своих проектах.
Исходники:
GitHub
Комментариев нет:
Отправить комментарий