Handling Application Lifecycle
1. Understanding Process Lifecycle
| State | Description | Key Methods |
|---|---|---|
| Created | Activity is created but not visible | onCreate() |
| Started | Activity is visible but not in focus | onStart() |
| Resumed | Activity is in focus and interactive | onResume() |
| Paused | Activity is partially obscured or in background | onPause() |
| Stopped | Activity is no longer visible | onStop() |
| Destroyed | Activity is being destroyed | onDestroy() |
Example: Lifecycle Callbacks in Kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
}
Note: The lifecycle methods are called in a specific order, and each state transition can trigger multiple callbacks.
2. Handling App Startup
| Component | Description | Usage |
|---|---|---|
| Application | Base class for maintaining global application state | Extend to manage app-level resources and initialization logic |
| onCreate() | Called when the application is starting | Initialize global variables, set up logging, or load configuration |
Example: Custom Application Class
import android.app.Application
import android.util.Log
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Log.d("MyApp", "Application started")
// Initialize global state here
}
}
Note: Register the custom Application class in
AndroidManifest.xml using the android:name attribute in the <application> tag.Key Points
- Application is the base class for maintaining global application state.
onCreate()is called once during app startup, before any activities or services are created.- Use
Applicationto initialize global resources or logging systems.
3. Managing Low Memory
| Property | Description | Notes |
|---|---|---|
| onLowMemory() | Called when the system detects that the application is running low on memory. | Invoked by the Android system; not guaranteed to be called. |
| onTrimMemory() | Called when the system determines that the application should trim its memory usage. | Provides a hint level for how much to trim. |
Example: Implementing onTrimMemory()
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
when (level) {
TRIM_MEMORY_RUNNING_MODERATE -> {
// Clean up moderate memory usage
cleanupCache()
}
TRIM_MEMORY_RUNNING_LOW -> {
// Clean up more aggressively
cleanupCache()
releaseUnnecessaryResources()
}
TRIM_MEMORY_RUNNING_CRITICAL -> {
// Clean up all non-essential resources
releaseAllResources()
}
}
}
Note:
onTrimMemory() is a more granular way to handle memory pressure compared to onLowMemory().Memory Trim Levels
TRIM_MEMORY_RUNNING_MODERATE: Application is running moderately low on memory.TRIM_MEMORY_RUNNING_LOW: Application is running low on memory.TRIM_MEMORY_RUNNING_CRITICAL: Application is running critically low on memory.
4. Handling App Visibility
| Property | Description | Usage |
|---|---|---|
| onStart() | Called when the app becomes visible to the user | Use to resume UI updates or start animations |
| onStop() | Called when the app is no longer visible to the user | Use to pause UI updates or stop animations |
| onResume() | Called when the app is in the foreground and interactive | Use to restore state or start foreground tasks |
| onPause() | Called when the app is partially obscured or going to background | Use to save state or pause foreground tasks |
Example: Managing Visibility in Activity
class MainActivity : AppCompatActivity() {
override fun onStart() {
super.onStart()
// App is now visible
Log.d("Lifecycle", "App started")
}
override fun onStop() {
super.onStop()
// App is no longer visible
Log.d("Lifecycle", "App stopped")
}
override fun onResume() {
super.onResume()
// App is in foreground
Log.d("Lifecycle", "App resumed")
}
override fun onPause() {
super.onPause()
// App is partially obscured
Log.d("Lifecycle", "App paused")
}
}
Note: These lifecycle methods are crucial for managing resources efficiently and ensuring a smooth user experience.
5. Implementing Lifecycle-Aware Components
Android's Lifecycle API allows components to observe the lifecycle state of an Android component and respond to changes without hardcoding lifecycle handling logic into the component itself.
| Component | Description | Key Methods |
|---|---|---|
| LifecycleOwner | Interface for components that own a lifecycle, such as Activities and Fragments. | getLifecycle() |
| LifecycleObserver | Interface for components that observe lifecycle changes. | onLifecycleEvent() |
| Lifecycle | Represents the lifecycle state of a component and provides methods to observe it. | addObserver(), removeObserver() |
Example: Creating a LifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
class MyLifecycleObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
// Handle start event
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
// Handle stop event
}
}
Example: Registering a LifecycleObserver
class MainActivity : AppCompatActivity(), LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
override fun getLifecycle(): Lifecycle {
return lifecycleRegistry
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val observer = MyLifecycleObserver()
lifecycleRegistry.addObserver(observer)
}
}
Note: Lifecycle-aware components are essential for managing resources efficiently and avoiding memory leaks in Android apps.
Key Concepts
- LifecycleOwner: Any object that can own a Lifecycle, such as an Activity or Fragment.
- LifecycleObserver: An object that observes lifecycle changes.
- Lifecycle.Event: Events like
ON_START,ON_STOP, etc., that can be observed.
6. Managing Configuration Changes
| Property | Description | Notes |
|---|---|---|
| onConfigurationChanged() | Callback method invoked when configuration changes occur | Must be declared in manifest with configChanges attribute to receive callback |
| configChanges | Manifest attribute to specify which configurations to handle in code | Values: screenSize, orientation, keyboardHidden, locale, etc. |
Example: Handling Configuration Changes
class MainActivity : AppCompatActivity() {
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
when (newConfig.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
// Handle landscape mode
}
Configuration.ORIENTATION_PORTRAIT -> {
// Handle portrait mode
}
}
}
}
Example: Manifest Declaration
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true">
</activity>
Note: When
configChanges is specified, the activity will not be restarted on configuration changes, and onConfigurationChanged is called instead.
Warning: Not declaring
configChanges in the manifest can lead to unnecessary activity recreation and loss of state.
7. Handling App Updates
| Update Type | Description | Implementation | Notes |
|---|---|---|---|
| In-App Updates | Allows users to update the app directly from within the app | |
Requires com.google.android.play:app-update dependency |
| Flexible Updates | Allows users to continue using the app while update downloads | |
Requires com.google.android.play:app-update dependency |
| Immediate Updates | Forces the app to update immediately, blocking user interaction | |
May interrupt user flow |
Example: Check for App Updates
val updateManager = UpdateManager(this)
updateManager.appUpdateInfo
.addOnSuccessListener { updateInfo ->
if (updateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
// Show update dialog or start update
}
}
Note: Ensure
AppUpdateManager is initialized in onCreate() of your main activity.Warning: Immediate updates can cause poor user experience if not handled carefully.
Update Handling Best Practices
- Use flexible updates for better UX
- Implement update progress tracking
- Handle update errors gracefully
8. Managing Multi-Window Mode
| Property | Description | Values |
|---|---|---|
| windowMode | Defines the current window mode of the activity | WINDOW_MODE_UNDEFINED, WINDOW_MODE_FULLSCREEN, WINDOW_MODE_SPLIT_SCREEN_PRIMARY, WINDOW_MODE_SPLIT_SCREEN_SECONDARY |
| isInMultiWindowMode | Checks if the activity is running in multi-window mode | true or false |
Example: Check Multi-Window Mode
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val isInMultiWindow = isInMultiWindowMode
if (isInMultiWindow) {
// Handle UI adjustments for multi-window mode
}
}
}
}
Example: Handle Window Mode Changes
class MainActivity : AppCompatActivity() {
override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean) {
super.onMultiWindowModeChanged(isInMultiWindowMode)
if (isInMultiWindowMode) {
// Adjust layout for multi-window mode
} else {
// Restore layout for full-screen mode
}
}
}
Note: Multi-window mode support requires Android N (API level 24) or higher.
Key Points
- Use
isInMultiWindowModeto detect if the app is in multi-window mode - Implement
onMultiWindowModeChanged()to respond to mode changes - Adjust UI layout and behavior for split-screen or floating window modes
9. Handling Picture-in-Picture
| Property | Description | Values |
|---|---|---|
| isPictureInPictureSupported | Checks if PiP is supported on the device | true / false |
| enterPictureInPictureMode | Enters Picture-in-Picture mode | PictureInPictureParams |
| pictureInPictureParams | Parameters for PiP mode configuration | PictureInPictureParams.Builder |
Example: Enter Picture-in-Picture Mode
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val pipParams = PictureInPictureParams.Builder()
.setAspectRatio(Rational(16, 9))
.build()
if (isPictureInPictureSupported) {
enterPictureInPictureMode(pipParams)
}
}
}
Note: Requires Android 8.0 (API level 26) or higher.
Warning: PiP mode is not available in all devices or configurations.
| Property | Description | Notes |
|---|---|---|
| PictureInPictureParams.Builder | Builder for PiP parameters | Used to configure aspect ratio and other settings |
| Rational | Represents a fraction (numerator/denominator) | Used for aspect ratio configuration |
10. Implementing App Shortcuts
App shortcuts allow users to quickly access specific features or content within your app directly from the home screen. These are supported on Android 7.1 (API level 25) and higher.
| Property | Description | Values |
|---|---|---|
| id | Unique identifier for the shortcut | string |
| shortLabel | Short label shown on the shortcut | string |
| longLabel | Longer label for accessibility | string |
| icon | Resource ID of the icon | int |
| intent | Intent to launch when shortcut is tapped | Intent |
Example: Defining App Shortcuts
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val shortcutManager = getSystemService(ShortcutManager::class.java)
val shortcuts = mutableListOf<ShortcutInfo>()
val shortcut = ShortcutInfo.Builder(this, "shortcut_id")
.setShortLabel("New Note")
.setLongLabel("Create a new note")
.setIcon(Icon.createWithResource(this, R.drawable.ic_note))
.setIntent(Intent(this, NoteActivity::class.java).apply {
action = Intent.ACTION_VIEW
putExtra("note_id", "new")
})
.build()
shortcuts.add(shortcut)
shortcutManager.setShortcuts(shortcuts)
}
}
Note: App shortcuts must be registered at runtime, typically in
onCreate or after the app is launched for the first time.
Warning: On Android 12 (API level 31) and above, you must declare the
android.permission.POST_NOTIFICATIONS permission to show app shortcuts.