Была идея. Собрать в одно место группу важных переменных, чтобы вместе они стали чем-то большим. И когда понадобятся, могли использоваться тогда, когда программисту нужны значения не зависящие от жизненных циклов и высвобождения памяти свернутых приложений.
![](https://habrastorage.org/getpro/habr/upload_files/f5c/530/7fd/f5c5307fd4876ad1ad3071b1a07d9b29.png)
Идея
Идея появилась из проблемы. Проблема появилась из негодования.
Мне было жутко неприятно от мысли, что при повороте экрана приходится проделывать серьезную работу над тем, чтобы сохранить состояние экрана в том виде, каком оно было до поворота.
Но еще больше негодования у меня вызвала новость, что поворот экрана это не единственная причина, которая может мешать мне сохранять состояние в неизменном виде.
Я ранее слышал про то, что система подчищает ресурсы для чего-то, забивая на свернутые приложения, но когда я немного углубился в это, то очень сильно был огорчен. Именно из этого "негодования" у меня появилась проблема. Как мне сделать это красиво и не так болезненно?
И из этой проблемы появилась идея. Идея собрать все, что должно быть независимо от поворота экрана и высвобождения памяти, в одно место, чтобы я в этом месте был уверен на все сто процентов и всегда знал: Все, что я туда положил, там и останется в неизменном виде.
И не хотелось сильно размазывать код этими переменными...
Каким образом решить эту задачу? Сразу вспоминаешь решения, которые уже есть: bundle и т.д.
Но мне одному все эти решения кажутся неудобными? Мне одному кажется, что они выписываются из общего кода, когда начинаешь с ними работать?
И тут я встал перед выбором, либо я делаю принципиально что-то новое, либо я делаю обертку чего-то, что уже придумано. Да такую обертку, чтобы с ней было удобней работать.
После анализа возможностей и моего знакомства с SavedStateHandle я загорелся желанием сделать обертку над ним и все это использовать в MVVM. Так и родилась библиотека которую сейчас Вы увидите.
Реализация
Ну тут все просто (имхо)
Например, мы уже определились со скоупом наших значений, которые мы хотим хранить. Тогда просто создаем класс в котором просто декларируем их и помечаем этот класс аннотацией @Unkillable
Например вот так:
@Unkillable
data class SampleFragmentState(
val testValue: Double,
val testLiveData: MutableLiveData<Double>
) : EmptyState()
Также мы можем там указать и произвольные классы, но только они уже должны быть с Parcelize (Подробней).
Таким образом должен выглядить ViewModel. Естественно, библиотека предлагает не только работу с AndroidViewModel, но и просто ViewModel.
class SampleViewModel(
application: Application,
savedStateHandle: SavedStateHandle
) : AndroidStateViewModel(application, savedStateHandle) {
override fun provideState() = createState<UnkillableSampleFragmentState>()
}
UnkillableSampleFragmentState сгенерируется у Вас сразу после запуска билда проекта.
Естественно, наша ViewModel должна быть проинициализированна, но не совсем так как обычно. А так, как предлагает Google для использования SavedStateHandle.
activity?.application?.let { application ->
viewModel = ViewModelProvider(this, SavedStateViewModelFactory(application, this))
.get(SampleViewModel::class.java)
}
Это все. Теперь можно использовать по назначению! Просто записываем туда данные и достаем их. Отмечу, что для сохранения класса необходимо делать его @Parcelize (Подробнее тут).
Вот таким образом можно воспользоваться библиотекой.
init {
// get values example
Log.d("StateLog", "0 value ${state.testValue}")
Log.d("StateLog", "1 value ${state.testLiveData?.value}")
}
fun onSetDataClicked() {
// set values example
state.testValue = 2.2
state.updateTestLiveDataValue(3.3) // yourLiveData.value = 3.3
state.postUpdateTestLiveDataValue(3.3) // yourLiveData.postValue(3.3)
}
Таким образом, мы защищаемся от подчистки приложения из памяти операционной системой.
Итог
Цель данной библиотеки упростить разработку и разгрузить разработчика от написания кода, при условии, что он работает с сохранением состояния приложения. Также удалось очистить код от всех этих переменных, которые необходимо сохранить. К тому же теперь они логически отделены от общей массы и не засоряют код, что выглядит довольно приятно. Однако пока сейчас она работает только в MVVM от гугла.
Ссылка на репозиторий UnkillableSavedState
GitHub