In-depth Analysis of Android Configuration Changes and Activity Restart Mechanism

Nov 20, 2025 · Programming · 14 views · 7.8

Keywords: Android Configuration Changes | Activity Restart | State Preservation | ViewModel | Application Class

Abstract: This article provides a comprehensive examination of Android's Activity restart mechanism triggered by device configuration changes such as screen rotation and keyboard visibility. It analyzes the system's default behavior and its impact on application state. Three primary solutions are detailed: using Application class for global initialization, preserving UI state with ViewModel, and manually handling changes via android:configChanges. Code examples illustrate implementation details and appropriate use cases for each approach, helping developers optimize user experience during configuration transitions.

Android Configuration Changes and Activity Restart Mechanism

In Android application development, device configuration changes (such as screen orientation rotation and keyboard availability) trigger the system's default Activity restart mechanism. When a configuration change occurs, the system destroys the current Activity instance and recreates a new one, causing the onCreate method to be called again. This mechanism ensures applications automatically adapt to new device configurations but also introduces state loss issues.

Types and Impact of Configuration Changes

Common configuration changes include screen orientation, keyboard availability, screen size, locale, font size, and system theme. These changes are typically triggered by user interactions like rotating the device or modifying system settings. Activity restart clears all state stored in the Activity instance and its contained objects like Fragments and Views. If not properly handled, this leads to lost user input or inconsistent application state.

Using Application Class for Global Initialization

For initialization code that needs to persist throughout the application lifecycle, it can be moved to a custom Application class. The Application class's onCreate method is called only when the application first starts and is not repeated during configuration changes.

Kotlin implementation example:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // Place application initialization code here
        initializeAppComponents()
    }
    
    private fun initializeAppComponents() {
        // Initialize network components, database, etc.
    }
}

Java implementation example:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // Place application initialization code here
        initializeAppComponents();
    }
    
    private void initializeAppComponents() {
        // Initialize network components, database, etc.
    }
}

Register the custom Application class in AndroidManifest.xml:

<application
    android:name=".MyApplication"
    ...>
    <activity ... />
</application>

Using ViewModel to Preserve UI State

ViewModel is part of Android's architecture components, specifically designed to retain UI-related data during configuration changes. ViewModel instances are not destroyed when Activities are recreated, maintaining data consistency.

Kotlin implementation example:

class MainViewModel : ViewModel() {
    private val _userData = MutableLiveData<String>()
    val userData: LiveData<String> = _userData
    
    fun updateUserData(data: String) {
        _userData.value = data
    }
}

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        
        // Observe data changes in ViewModel
        viewModel.userData.observe(this) { data ->
            // Update UI
            updateUIWithData(data)
        }
    }
    
    private fun updateUIWithData(data: String) {
        // Update interface based on data
    }
}

Manual Handling of Configuration Changes

By configuring the android:configChanges attribute, you can prevent the system from automatically handling specific configuration changes, instead handling them manually within the application.

Configuration in AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:label="@string/app_name">
</activity>

Then override the onConfigurationChanged method in the Activity:

Kotlin implementation example:

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    
    // Update UI based on new configuration
    when {
        newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE -> {
            // Landscape layout handling
            setContentView(R.layout.activity_main_landscape)
        }
        newConfig.orientation == Configuration.ORIENTATION_PORTRAIT -> {
            // Portrait layout handling
            setContentView(R.layout.activity_main_portrait)
        }
    }
    
    // Check keyboard availability
    if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) {
        // Handle keyboard visibility
        handleKeyboardVisible()
    }
}

Best Practices for State Preservation and Restoration

Regardless of the chosen approach, proper handling of application state preservation and restoration is essential:

  1. Use onSaveInstanceState: Save temporary UI state
  2. Persistent storage: Use databases or SharedPreferences for important data
  3. Avoid memory leaks: Ensure resource release when Activity is destroyed
  4. Test various scenarios: Include configuration changes, process death, and other edge cases

State preservation example:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    // Save current state
    outState.putString("user_input", editText.text.toString())
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    // Restore saved state
    savedInstanceState?.getString("user_input")?.let { savedText ->
        editText.setText(savedText)
    }
}

Performance Optimization Considerations

When handling configuration changes, consider performance impacts:

Compatibility Considerations

Different Android versions handle configuration changes differently:

By appropriately selecting and implementing configuration change strategies, developers can significantly enhance application user experience, ensuring consistent and smooth operation across various device configurations.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.