Senior Android Developer Interview Questions and Answers: Lifecycle

Sandeep Kella
5 min readApr 18, 2024

--

These questions target senior developers with a deep understanding of Activity and Fragment lifecycles and their impact on app behavior.

Deep Dive into Lifecycle Methods:

  • Q: Explain the difference between onSaveInstanceState() and onRestoreInstanceState() and when you would use each one.
  • A:
  • onSaveInstanceState(): Called by the system before an Activity/Fragment is destroyed (configuration changes like screen rotation). Save essential UI state or data here. This data is stored in a Bundle.
  • onRestoreInstanceState(): Called after an Activity/Fragment is recreated, following a configuration change. Retrieve data saved in onSaveInstanceState() to restore the UI state.
  • Q: How can you leverage onSaveInstanceState() for persisting complex data structures across configuration changes?
  • A: onSaveInstanceState() isn't ideal for complex data. Here are alternatives:
  • Parcelable: Implement Parcelable for custom objects to serialize them for storage in the Bundle.
  • ViewModel: Use ViewModels for data tightly coupled to the Activity/Fragment lifecycle. They persist data across configuration changes in a lifecycle-aware holder.
  • Room: For persistent data beyond configuration changes/app restarts, use a Room database. It simplifies database interactions and data persistence.
  • Q: Discuss scenarios where you might avoid using onSaveInstanceState() and explore alternative approaches.
  • A: Avoid onSaveInstanceState() for:
  • Large data sets (increases Bundle size, potentially leading to crashes).
  • UI state easily recreated based on business logic or server-fetched data.
  • Q: Explain the concept of the LifecycleOwner interface and its role in managing the lifecycle of LiveData objects.
  • A: LifecycleOwner identifies components with observable lifecycles (Activities, Fragments).
  • LiveData is an observable data holder class from Jetpack Lifecycle. It's lifecycle-aware, only emitting updates to observers when the LifecycleOwner is active (RESUMED). This prevents data updates at inappropriate times.
  • Q: How would you implement a custom lifecycle observer to handle specific events in your app?
  • A: 1. Create a class implementing LifecycleObserver. 2. Implement methods for desired lifecycle events (e.g., @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)). 3. In your Activity/Fragment, get a reference to the LifecycleOwner (usually this). 4. Use getLifecycle().addObserver() to register your observer with the LifecycleOwner. 5. Perform actions in observer methods for specific lifecycle stages.

Lifecycle and Memory Management:

  • Q: Describe best practices for handling background tasks and network requests during different Activity/Fragment lifecycle states.
  • A:
  • onCreate(): Lightweight initialization tasks.
  • onStart(): Good place to start background tasks or network requests (Activity/Fragment is fully visible).
  • onResume(): For data crucial for immediate display (consider user experience and potential delays).
  • onPause(): Pause or cancel long-running tasks or network requests that aren't essential while paused.
  • onStop(): Release resources associated with background tasks, network requests, or database connections to avoid leaks.
  • onDestroy(): Final cleanup tasks (closing cursors, unregistering receivers).
  • Q: How can you ensure proper resource management (releasing network connections, closing cursors) in lifecycle methods to avoid leaks?
  • A:
  • Network connections (Retrofit, Volley): Libraries handle connections internally, but in custom code, close connections explicitly (typically in onPause() or onStop()).
  • Cursors (Room/CursorLoader): Follow recommended practices for closing cursors (Room usually handles this, but manual closing might be needed in specific scenarios).
  • Broadcast receivers: Unregister them in onDestroy() or onStop() to prevent leaks (especially if registered dynamically).
  • Location updates: Stop requesting location updates when paused/stopped to conserve battery and avoid unnecessary resource usage.

Advanced Lifecycle Scenarios (continued)

  • Q: How would you design an Activity that can handle multiple configurations (like split-screen mode) while maintaining a consistent user experience?
  • A:
  • Utilize onConfigurationChanged(): Override this method in your Activity to handle configuration changes. Detect the new configuration and adjust UI layout or behavior accordingly.
  • Responsive layouts: Use techniques like ConstraintLayout or FlexboxLayout to create layouts that adapt to different screen sizes and orientations.
  • Test thoroughly: Test your Activity in various configurations (split-screen, different screen sizes) to ensure a seamless user experience.
  • Q: Explain the challenges of working with background services and their interaction with the Activity/Fragment lifecycle.
  • A:
  • Background services can outlive Activities/Fragments: Be cautious about references to Activities/Fragments within the service, as they might be destroyed while the service is still running. Use weak references or unbind services when no longer needed.
  • Lifecycle-aware communication: If communication is necessary between background services and Activities/Fragments, consider well-defined communication mechanisms (e.g., BroadcastReceivers, LiveData) that don’t directly rely on the lifecycle of the Activity/Fragment.
  • Q: Discuss how you would approach implementing a long-running task that persists even if the user navigates away from the Activity?
  • A:
  • Foreground Service: If the task requires user notification or ongoing interaction (like playing music), consider using a Foreground Service. It displays a persistent notification, indicating a long-running operation.
  • WorkManager: For more general background tasks without user notification, use WorkManager. It’s a flexible API for scheduling and managing background work, ensuring tasks are executed even if the app is closed or the device reboots.
  • Q: How can you leverage LifecycleScope for coroutines and avoid memory leaks related to coroutine jobs?
  • A:
  • LifecycleScope: Use lifecycleScope or viewModelScope within your Activity/Fragment to launch coroutines tied to the lifecycle. These scopes are automatically canceled when the Activity/Fragment is destroyed, preventing memory leaks associated with uncompleted coroutine jobs.
  • Job cancellation: For coroutines launched outside of a lifecycle scope, manually cancel them when they’re no longer needed to avoid leaks.

Problem-Solving with Lifecycle (continued)

  • Q: The user reports an issue where data displayed in a Fragment disappears after screen rotation. How would you investigate and fix this problem considering the Fragment lifecycle?
  • A:
  • Investigate Fragment recreation: Check if the Fragment is being recreated due to screen rotation. This might be happening if you’re not persisting the data properly.
  • Review onSaveInstanceState() and onRestoreInstanceState(): Ensure these methods are implemented correctly to save and restore the data associated with the Fragment's UI state.
  • Consider using ViewModel: If the data is tightly coupled to the Fragment’s lifecycle, use a ViewModel to store the data. ViewModels persist data across configuration changes in a lifecycle-aware holder.
  • Q: Your app experiences crashes during configuration changes. How would you identify if the issue is related to the Activity/Fragment lifecycle and how to potentially solve it?
  • A:
  • Analyze crash logs: Look for errors or exceptions occurring during lifecycle methods like onCreate() or onConfigurationChanged().
  • Review lifecycle handling: Ensure you’re properly handling configuration changes (using onConfigurationChanged()), restoring state with onRestoreInstanceState(), and avoiding resource leaks (releasing resources in onStop() and onDestroy()).
  • Consider using leak canaries: Tools like LeakCanary or MatLeaked can help identify memory leaks that might contribute to crashes during configuration changes.
  • Q: You are tasked with optimizing battery life for an app that uses location updates. How can you leverage the Activity/Fragment lifecycle to minimize battery drain?
  • A:
  • Request location updates only when needed: Use requestLocationUpdates() with appropriate intervals and accuracy levels based on your app's requirements. Stop requesting updates in onPause() or onStop() when location information isn't crucial.
  • Consider alternatives: If continuous location updates aren’t necessary, explore alternatives like geofencing or periodic location checks to reduce battery usage.
  • Use LocationManager.isProviderEnabled(): Check if location services are enabled before requesting updates to avoid unnecessary battery drain.

By understanding these advanced concepts and how to apply them in various scenarios, you can demonstrate your expertise in handling complex lifecycle interactions and building robust and optimized Android apps.

--

--

Sandeep Kella

Android developer @PhonePe, writes about Android development and productivity.