The mobile app lifecycle
On a desktop, a program runs until the user closes it. On a phone, the operating system decides. Memory, battery and network are scarce, so the OS pauses, freezes and kills apps constantly. Your app has to expect this.
The states
Both platforms follow the same broad shape.
- Foreground / active: visible and receiving input.
- Background: not visible. The app may run briefly, for example to finish saving.
- Suspended: in memory but not executing any code.
- Terminated: the process is gone. The OS can kill a suspended app at any time without telling it.
On iOS, a UIScene moves through sceneWillEnterForeground, sceneDidBecomeActive, sceneWillResignActive and sceneDidEnterBackground. After a short window in the background the app is suspended.
On Android, each Activity receives onCreate, onStart, onResume, onPause, onStop and onDestroy. An activity is also destroyed and recreated on configuration changes, such as rotating the device or switching to dark mode, unless you handle them yourself.
The rule: save early, assume death
Because a suspended app can be killed silently, there is no reliable “app is closing” callback. Save user work when the app leaves the foreground: in onPause/onStop on Android, or on sceneDidEnterBackground / sceneWillResignActive on iOS.
class EditorActivity : AppCompatActivity() {
override fun onStop() {
super.onStop()
draftRepository.save(editor.text.toString()) // persist before we can be killed
}
}
Keep two kinds of state apart:
- UI state (scroll position, the half-typed search) is restored through
onSaveInstanceState/SavedStateHandleon Android and state restoration on iOS. - User data (a drafted message, an unsent form) belongs in durable storage: a database or files.
On Android, a ViewModel survives configuration changes but not process death. Combine it with SavedStateHandle for small UI state, and with persistent storage for anything the user would be upset to lose.
Background work is restricted
Both platforms limit what apps do in the background to protect battery life.
- On iOS, background execution is allowed only for specific purposes: audio, location, VoIP, short tasks requested with
beginBackgroundTask, and deferred work throughBGTaskScheduler. The system decides when deferred work runs. - On Android, background services are restricted. Use WorkManager for deferrable, guaranteed work such as syncing, with constraints like “only on Wi-Fi” or “only while charging”. Use a foreground service, with a visible notification, for work the user is actively aware of, like navigation or music.
Push notifications, not polling, are the way to learn about server changes while in the background.
Network and battery
- Networks are slow, flaky and metered. Cache aggressively, retry with backoff, and design screens to work offline where possible.
- The radio uses a lot of power when it wakes up. Batch requests instead of sending many small ones.
- Test with the network throttled and in airplane mode, and test process death: Android’s developer options include “Don’t keep activities”, which destroys each activity as soon as you leave it.