Враћање стања (State Restoration) је механизам мобилних оперативних система који омогућава чување и враћање корисничког интерфејса апликације након њеног поновног покретања или минимизирања. Систем чува стање UI у меморији или трајном складишту и враћа га при поновном отварању. Према подацима Android Developers (2025), State Restoration је обавезан за апликације које теже квалитетном корисничком искуству. State Restoration је критично важан за спречавање губитка података при неочекиваном затварању апликације.
Главне тачке
State Restoration (враћање стања) је системски механизам који омогућава чување тренутног стања корисничког интерфејса апликације и његово враћање након затварања или поновног покретања. Када корисник минимизира апликацију или је систем затвори ради ослобађања ресурса, State Restoration бележи кључне параметре UI и чува их у шифрованом складишту.
Без State Restoration, корисник губи све несачуване податке при пребацивању између апликација. На пример, попуњен образац за контакт, дуга претрага или делимично прегледана листа вести — све то нестаје при поновном покретању. State Restoration решава овај проблем аутоматским бележењем стања ViewController или Activity у тренутку минимизирања.
Механизам ради на системском нивоу и подржан је од обе главне мобилне платформе. iOS пружа State Restoration кроз NSUserActivity и протокол UIStateRestoring, а Android — кроз SavedStateHandle у архитектонским компонентама Jetpack и ViewModel. Имплементација се разликује, али концепт је идентичан.
Процес State Restoration се дели на две фазе: чување (save) и враћање (restore). У фази чувања, систем позива одговарајуће методе животног циклуса у којима апликација мора да серијализује тренутно стање UI у компактни приказ. У фази враћања, систем прослеђује сачуване податке назад, а апликација их десеријализује ради враћања UI.
Чување покреће систем при преласку апликације у позадину или при пријему сигнала о скором затварању. У iOS се позива метода encodeRestorableState у UIViewController, у Android — onSaveInstanceState у Activity или чување кроз SavedStateHandle. Подаци се серијализују у формат који подржава примитивне типове: низове знакова, бројеве, бајт низове и Parcelable објекте.
Обим сачуваних података треба да буде минималан — систем намеће ограничења на величину сачуваног пакета. У Android-у граница износи приближно 50 KB по процесу. Прекорачење границе доводи до изузетка TransactionTooLargeException. Због тога архитекте препоручују чување само идентификатора и кључева, а комплетне податке учитавати из трајног складишта при враћању.
При враћању, систем прослеђује сачувани пакет података апликацији у тренутку покретања. У iOS се позива метода decodeRestorableState, у Android — onRestoreInstanceState или читање из SavedStateHandle. Апликација издваја идентификаторе и кључеве из пакета и враћа UI: позицију померања, изабране елементе, унете податке.
Важно је узети у обзир да се враћање може десити у новом процесу. Ако је апликација потпуно истоварена из меморије, процес се ствара изнова и сви објекти у меморији недостају. Стога стање мора бити серијализујуће и независно од контекста извршавања претходне сесије. Ово је посебно критично за велике формуларе са мноштвом поља за унос и дугачке вишестраничне интерфејсе.
class MainActivity : AppCompatActivity() {
private var searchQuery: String = ""
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("search_query", searchQuery)
}
override fun onRestoreInstanceState(savedState: Bundle) {
super.onRestoreInstanceState(savedState)
searchQuery = savedState.getString("search_query", "")!!
restoreSearchUI(searchQuery)
}
}
Имплементација State Restoration се значајно разликује између платформи. iOS користи декларативни приступ кроз storyboard и протоколе UIKit, а Android — императивни кроз методе животног циклуса Activity и архитектонске компоненте Jetpack. Избор приступа зависи од циљне платформе и архитектуре апликације.
У iOS-у, State Restoration се заснива на три компоненте: UIApplication управља целокупним процесом, UIViewController имплементира протокол UIStateRestoring, а NSUserActivity чува податке за враћање навигације. За активирање потребно је поставити restorationIdentifier у UIViewController и имплементирати encodeRestorableState и decodeRestorableState.
iOS аутоматски чува стање навигационог контролера (UINavigationController) и свих угњеждених ViewController-а, ако имају постављен restorationIdentifier. Систем управља стеком навигације и враћа га у првобитно стање. Међутим, подаци унутар контролера (унети текст, позиција померања) морају бити експлицитно сачувани од стране програмера.
У Android-у, модеран приступ State Restoration-у заснива се на SavedStateHandle — компоненти из библиотеке AndroidX Lifecycle. SavedStateHandle је доступан унутар ViewModel и аутоматски чува и враћа податке при промени конфигурације (ротација екрана) и при поновном покретању процеса. Подаци се чувају у Bundle и аутоматски серијализују.
SavedStateHandle се понаша као складиште кључ-вредност са подршком за LiveData. При промени конфигурације, подаци се аутоматски чувају и враћају. За подршку поновном покретању процеса, ViewModel мора бити креиран кроз SavedStateViewModelFactory — то омогућава ViewModel-у да преживи потпуно затварање апликације.
class SearchViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
companion object {
private val KEY_QUERY = string("search_query")
}
fun getSearchQuery(): String? = savedStateHandle[KEY_QUERY]
fun saveSearchQuery(query: String) {
savedStateHandle[KEY_QUERY] = query
}
}
Практична имплементација State Restoration захтева узимање у обзир неколико аспеката: избор одговарајућег складишта, одређивање обима сачуваних података и тестирање различитих сценарија затварања. Размотримо имплементацију корак по корак за Flutter апликацију коришћењем пакета state_restoration.
class RestorableSearchField extends RestorableProperty<String> {
String _value = '';
@override
String get value => _value;
@override
void set value(String newValue) {
if (_value != newValue) {
_value = newValue;
notifyListeners();
}
}
@override
String? toPrimitives() => _value;
@override
void fromPrimitives(String? data) {
_value = data ?? '';
}
}
При имплементацији важно је запамтити границе чувања. Није свако UI поље потребно враћати. Позиција померања у дугачкој листи — да. Привремено стање анимације — не. Програмер треба свесно да бира који подаци су критични за корисничко искуство, а који се могу безбедно ресетовати без губитка удобности.
Тестирање State Restoration-а је посебан задатак који захтева симулацију затварања процеса. На Android-у се то може урадити командом adb shell am kill, на iOS-у — симулацијом затварања у Xcode-у. Оквири за тестирање UI, попут Espresso и XCTest, пружају посебне методе за проверу враћања стања.
Прво правило — чувајте идентификаторе, а не податке. Уместо чувања комплетног објекта са стотинама поља, сачувајте његов јединствени идентификатор, а при враћању учитајте актуелне податке из базе података или API-ја. Ово штеди простор у Bundle-у и гарантује актуелност података у тренутку враћања.
Друго правило — тестирајте све сценарије. Проверите враћање након ротације екрана, након минимизирања и повратка после сат времена, након затварања апликације од стране система због недостатка меморије. Сваки сценарио се може понашати другачије у зависности од стања оперативног система и доступних ресурса.
Треће правило — користите системске механизме, а не сопствене. iOS и Android пружају уграђене API-је за State Restoration који су оптимизовани за одређену платформу. Сопствена имплементација кроз SharedPreferences или UserDefaults може довести до проблема са синхронизацијом и неочекиваног понашања при враћању.
Четврто правило — обрађујте одсуство стања. При првом покретању или након чишћења података, стање може да изостане. UI мора да ради исправно у почетном стању без бацања изузетака. Проверавајте све сачуване податке на null пре употребе и предвидите подразумеване вредности.
Пето правило — документујте сачуване кључеве. Када у пројекту постоје десетине екрана и сваки чува неколико поља, без централизованог управљања кључевима настаје хаос. Направите јединствену класу или датотеку са константама кључева за State Restoration у сваком модулу. Ово поједностављује одржавање и спречава случајно преписивање података при рефакторисању.
Често постављана питања
State Restoration — механизам чувања и враћања корисничког интерфејса апликације након поновног покретања или минимизирања, који спречава губитак података и контекста рада корисника.
State Restoration чува привремено стање UI (позицију померања, унете податке у формулару), док база података чува трајне корисничке податке. State Restoration користи системске механизме (Bundle, NSData) са ограничењем обима.
Користите SavedStateHandle у ViewModel из AndroidX Lifecycle. Он аутоматски чува податке при минимизирању и враћа их при повратку. За подршку потпуног поновног покретања користите SavedStateViewModelFactory.
Поставите restorationIdentifier у UIViewController и имплементирајте методе encodeRestorableState и decodeRestorableState. За навигацију користите NSUserActivity са чувањем путање у стеку контролера.
Чувајте идентификаторе, а не комплетне податке: ID изабраног елемента, претрагу, позицију померања, стање прекидача. Избегавајте чување великих објеката и слика.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође