Configuration Changes, State Saving and Process Death

Configuration Changes, State Saving and Process Death

1. What is a configuration change?

A configuration change happens when the device or application environment changes.

Examples:

* Screen rotation

* Language change

* Light or dark theme change

* Font scale change

* Screen size change

* Foldable device state change

* Keyboard availability change

Android normally destroys and recreates the Activity so it can load resources matching the new configuration.

---

2. Rotation flow

Portrait Activity
      |
Device rotated
      |
onPause()
      |
onStop()
      |
onDestroy()
      |
New landscape Activity
      |
onCreate()
      |
onStart()
      |
onResume()

The old Activity object is destroyed.

A new Activity object is created with resources such as:

res/layout/activity_main.xml
res/layout-land/activity_main.xml

---

3. Language change

When the application language changes:

Old Activity
    |
Destroyed
    |
New Activity created
    |
Localized resources loaded

Example resources:

res/values/strings.xml
res/values-hi/strings.xml
res/values-fr/strings.xml

---

4. Theme change

Changing between light and dark mode can also recreate the Activity.

Light theme Activity
       |
Night mode changes
       |
Activity recreated
       |
Dark theme resources loaded

Resources can come from:

values/themes.xml
values-night/themes.xml

---

5. ViewModel retention

ViewModel survives configuration changes.

Activity A
    |
Rotation
    |
Activity A destroyed
    |
Activity B created
    |
Same ViewModel returned
class ProductViewModel : ViewModel() {

    var selectedProductId: String? = null
}

Obtain it:

private val viewModel: ProductViewModel by viewModels()

ViewModel survives

* Rotation

* Language-related Activity recreation

* Theme-related Activity recreation

* Other normal configuration changes

ViewModel does not survive

* System process death

* App force-stop

* Normal final Activity finish

* Device reboot

---

6. Saved instance state

savedInstanceState stores small UI-related values.

private var selectedTab = 0

override fun onSaveInstanceState(outState: Bundle) {
    outState.putInt("selected_tab", selectedTab)
    super.onSaveInstanceState(outState)
}

Restore:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    selectedTab =
        savedInstanceState?.getInt("selected_tab") ?: 0
}

Saved state can help restore UI after both configuration changes and system-initiated process death, but Bundles should contain only small, serializable state.

Good saved-state values:

* Selected tab

* Scroll position

* Search query

* Entered text

* Selected item ID

* Filter option

Bad saved-state values:

* Large API responses

* Bitmaps

* Complete database lists

* Repository objects

* Network clients

---

7. SavedStateHandle

SavedStateHandle provides saved state inside a ViewModel.

class SearchViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    val query = savedStateHandle.getStateFlow(
        "search_query",
        ""
    )

    fun updateQuery(value: String) {
        savedStateHandle["search_query"] = value
    }
}

It combines two useful behaviors:

ViewModel
Survives configuration changes

SavedStateHandle
Restores small values after process recreation

SavedStateHandle is suitable for small reconstruction information such as IDs, queries and filters—not for storing large business data.

---

8. Process death

During process death, all in-memory objects are lost.

Activity              -> Lost
Fragment              -> Lost
ViewModel             -> Lost
Application object    -> Lost
Singleton             -> Lost
Static variables      -> Lost
Coroutine scopes      -> Lost

Persistent or saved data may remain:

Saved instance state  -> Restorable
SavedStateHandle      -> Restorable
Room                  -> Remains
DataStore             -> Remains
Files                 -> Remain
Server data           -> Remains

---

9. Correct state reconstruction

Instead of saving complete data, save enough information to reload it.

Bad:

savedStateHandle["complete_product"] = largeProductObject

Better:

savedStateHandle["product_id"] = product.id

Then reconstruct:

Saved product ID
      |
New ViewModel created
      |
Read product ID
      |
Repository loads product
      |
Room/API provides latest data
      |
UI state rebuilt

Example:

class ProductViewModel(
    savedStateHandle: SavedStateHandle,
    repository: ProductRepository
) : ViewModel() {

    private val productId: String =
        checkNotNull(savedStateHandle["product_id"])

    val product = repository.observeProduct(productId)
}

---

10. Process death testing

Method 1: ADB process kill

1. Open the required application screen.

2. Press Home so the app moves to the background.

3. Run:

adb shell am kill com.example.app

4. Open the app again from the launcher or Recents.

5. Check whether state is reconstructed.

Android’s lifecycle codelab uses this approach to simulate the system killing a background process.

Method 2: “Don’t keep activities”

Enable:

Developer options
    |
Don't keep activities

This destroys Activities when the user leaves them.

Important:

> “Don’t keep activities” is useful for finding Activity recreation problems, but it is not exactly the same as full application process death.

Avoid force-stop for normal restoration testing

Force-stop represents a user-directed app dismissal. Saved task state might not be restored in the same way as system-initiated process death.

---

11. State-management decision table

RequirementSolution
Survive rotationViewModel
Restore small UI stateSaved instance state
Save state inside ViewModelSavedStateHandle
Save structured business dataRoom
Save settingsDataStore
Save large dataDatabase, file or server
Reliable background operationWorkManager
Restore screenSaved ID + repository reload

---

Interview answer

> Configuration changes normally destroy and recreate the Activity. ViewModel survives configuration changes but does not survive process death. Small UI values can be saved using saved instance state or SavedStateHandle. Important or large business data should be stored in Room, DataStore, files or a server. After process death, the app should reconstruct the screen using saved IDs, queries or filters and reload the real data from a repository.