Android Basics
Android Basics Interview with follow-up questions
1. Can you explain the Android application life cycle?
The Android application life cycle describes the sequence of states an app process and its components go through from launch to termination. Understanding it is critical because the system can kill your process at any time to reclaim memory, and your app must save and restore state correctly to feel reliable to users.
Application-level life cycle (Application class)
The Application object is created before any activity, service, or broadcast receiver. Application.onCreate() is the right place to initialize global singletons — dependency injection graphs (Hilt's @HiltAndroidApp), crash reporting, networking clients — because it runs exactly once per process lifetime.
Component-level life cycle
Each UI component (Activity, Fragment, composable in Compose) has its own life cycle on top of the application life cycle. The system orchestrates these through the Lifecycle owner/observer pattern from Jetpack (androidx.lifecycle).
Process importance hierarchy
The system decides which processes to kill based on importance:
- Foreground process (running activity, bound foreground service)
- Visible process (paused activity still visible)
- Service process (background service)
- Cached process (stopped activity, eligible for killing)
When memory pressure hits, cached processes are killed first. Your app's state disappears with the process, so you must persist what matters.
Key gotchas interviewers probe
onCreatevs. cold vs. warm start: a cold start creates a new process; a warm start restores a cached process.onCreateis called on cold start only.onTrimMemory: called at various levels (TRIM_MEMORY_UI_HIDDEN,TRIM_MEMORY_RUNNING_CRITICAL) to signal you should release caches. Ignoring it causes the system to kill your process sooner.- Background restrictions: from Android 8+ (Oreo), background execution is heavily restricted. Apps can't start background services freely; use
WorkManagerfor deferrable work and foreground services (with a notification) for user-visible ongoing work. - Don't confuse Application life cycle with Activity life cycle: the Application exists for the entire process lifetime, spanning multiple activities.
- Hilt and DI: In modern apps,
@HiltAndroidAppon the Application subclass bootstraps the Hilt component graph. Forgetting this annotation is a common mistake.
Follow-up 1
What is the role of the onCreate() method in the life cycle?
The onCreate() method is called when the application is first created. It is responsible for initializing essential components of the application, such as UI elements and data structures. This method is typically used to set up the initial state of the application and prepare it for user interaction.
Follow-up 2
What happens when an Android application is in the onStop() state?
When an Android application is in the onStop() state, it is no longer visible to the user. This can happen when another application is launched or when the user navigates away from the current application. In this state, the application may be paused or even terminated by the system if resources are needed. However, the application can still be resumed and brought back to the foreground by the user or the system.
Follow-up 3
How does the onDestroy() method affect the application life cycle?
The onDestroy() method is called when the application is about to be terminated or destroyed. It is the final method in the life cycle and is typically used to release any resources or clean up any connections that the application has established. After the onDestroy() method is called, the application is no longer running and cannot be resumed.
Follow-up 4
What is the difference between onPause() and onStop() in the Android life cycle?
The onPause() method is called when the application is about to lose focus or become partially visible. It is typically used to pause ongoing activities or operations that should not continue while the application is in the background. On the other hand, the onStop() method is called when the application is no longer visible to the user. It is a more significant event than onPause() and indicates that the application may be paused or even terminated by the system if resources are needed.
2. What is an activity in Android and how does its life cycle work?
An Activity represents a single screen the user interacts with. In Jetpack Compose, you typically have one or very few activities and navigate between screens using the Compose Navigation library (NavHost, NavController) rather than starting new activities. The activity still exists as the entry point, but the UI lives in composables. In a View-based app, each screen tends to be a separate activity or fragment.
Activity life cycle callbacks
onCreate(savedInstanceState): Called when the activity is first created or recreated after process death. Initialize UI, set up ViewModel, callsetContent {}(Compose) orsetContentView()(XML).savedInstanceStateis non-null when recreating after system-initiated kill.onStart(): Activity becomes visible but not yet interactive.onResume(): Activity is in the foreground and receiving input. Safe to start animations and sensors here.onPause(): Another activity is coming to the foreground. Keep work here brief — the next activity won't resume untilonPausereturns. Release sensors, camera, or anything that should not run in the background.onStop(): Activity is no longer visible. A good place to release heavier resources or save non-critical state.onStopis guaranteed to be called beforeonDestroyon Android 3.0+.onDestroy(): Activity is finishing (user dismissed it orfinish()was called) or being recreated due to configuration change. CheckisFinishing()to distinguish.onRestart(): Called beforeonStart()when the activity returns from the stopped state.
Configuration changes
Rotating the screen or changing locale destroys and recreates the activity by default. A ViewModel survives this because it lives outside the activity. In Compose, rememberSaveable persists state across recompositions and configuration changes; plain remember does not.
Saved instance state vs. ViewModel
ViewModel: survives configuration changes, does not survive process death. Good for holding data fetched from the network.savedInstanceState/rememberSaveable: survives both configuration changes and process death (restored by the system). Limited to a small Bundle. Use for transient UI state (scroll position, selected tab).- Persistent storage (Room, DataStore): survives everything, including uninstall-reinstall.
Back stack
Activities are managed on a task's back stack. launchMode in the manifest (singleTop, singleTask, singleInstance) and Intent flags control how activities stack. In practice, most modern apps use Compose Navigation which manages a NavBackStack instead.
Common gotcha: onPause is not a safe place to save critical data to a database — it must be quick. Do disk I/O in onStop or better yet, auto-save in the ViewModel via viewModelScope.
Follow-up 1
What is the significance of the onResume() method in an activity's life cycle?
The onResume() method is an important callback method in an activity's life cycle. It is called when the activity is about to become visible to the user and regain focus. This is the ideal place to perform tasks that need to be resumed or refreshed, such as refreshing data from a database or updating the UI. It is also a good place to register listeners or start animations. onResume() is always followed by onStart() and onStop() methods.
Follow-up 2
How does the system manage the life cycle of an activity?
The system manages the life cycle of an activity by calling specific callback methods at different stages. When an activity is first created, the onCreate() method is called. This is where initialization tasks, such as setting up the UI and binding data, should be performed. When the activity becomes visible to the user, the onStart() method is called. This is where the activity prepares to become active and interact with the user. When the activity is resumed and comes to the foreground, the onResume() method is called. This is where the activity should start or resume any actions that were paused or stopped. When the activity is no longer visible to the user, the onPause() method is called. This is where the activity should save any unsaved data or release any resources that are no longer needed. Finally, when the activity is destroyed, the onDestroy() method is called. This is where the activity should clean up any resources and perform final cleanup.
Follow-up 3
What is the difference between onStart() and onResume() in an activity's life cycle?
The onStart() and onResume() methods are both callback methods in an activity's life cycle, but they are called at different stages. The onStart() method is called when the activity is becoming visible to the user, but it may not yet be in the foreground and have focus. This is where the activity prepares to become active and interact with the user. On the other hand, the onResume() method is called when the activity is about to regain focus and become fully visible to the user. This is where the activity should start or resume any actions that were paused or stopped. In summary, onStart() is called before the activity is fully visible, while onResume() is called when the activity is about to regain focus and become fully visible.
Follow-up 4
What happens when an activity enters the onPause() state?
When an activity enters the onPause() state, it means that the activity is no longer in the foreground and is partially visible to the user. This can happen when another activity comes to the foreground, such as when the user receives a phone call or opens another app. In this state, the activity should save any unsaved data or release any resources that are no longer needed. It is also a good place to unregister listeners or stop animations. The onPause() method is always followed by either onResume() if the activity comes back to the foreground, or onStop() if the activity is completely hidden or destroyed.
3. Can you explain the life cycle of a fragment in Android?
Fragments are still widely used in View-based apps alongside the Navigation Component, but in Jetpack Compose the concept of a composable screen largely replaces them — you navigate between composable destinations rather than fragment transactions. That said, Fragments remain important for hybrid codebases and for interop with Compose inside a ComposeView.
Fragment life cycle callbacks
onAttach(context): Fragment is attached to its host Activity. The context is available here.onCreate(savedInstanceState): Fragment is created. Initialize non-UI data — arguments, ViewModel references. Do not reference views yet.onCreateView(inflater, container, savedInstanceState): Inflate and return the fragment's view hierarchy. For Compose fragments, return aComposeViewhere.onViewCreated(view, savedInstanceState): The view is fully created. This is the right place to bind views, set up click listeners, and observe ViewModels.onStart(): Fragment becomes visible.onResume(): Fragment is interactive.onPause(): Fragment is losing focus.onStop(): Fragment is no longer visible.onDestroyView(): The view hierarchy is being destroyed. Critical: clear any references to views orViewBindinghere to prevent memory leaks. Set the binding field tonull.onDestroy(): Fragment itself is being destroyed.onDetach(): Fragment is detached from the Activity.
Fragment has two separate life cycles: the fragment's own and its view's. This is the most common interview gotcha. The view life cycle goes from onCreateView to onDestroyView, while the fragment's life cycle can persist beyond that (e.g., in the back stack). Always observe LiveData/Flow using viewLifecycleOwner, not this, to avoid receiving updates on a destroyed view.
// Correct — uses viewLifecycleOwner
viewModel.data.observe(viewLifecycleOwner) { data -> ... }
// Wrong — leaks and may crash when the view is gone
viewModel.data.observe(this) { data -> ... }
onActivityCreated() is deprecated as of Fragment 1.3. Move its logic to onViewCreated() or onCreate().
Back stack and transactions
When a fragment is placed on the back stack (via addToBackStack()), onDestroyView() is called but onDestroy() is not — the fragment instance is kept alive. When the user presses back, onCreateView() runs again. This is why you must null out the binding in onDestroyView().
ViewBinding in fragments
private var _binding: FragmentExampleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(...) = FragmentExampleBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
Follow-up 1
How does the fragment life cycle differ from the activity life cycle?
The fragment life cycle is closely related to the activity life cycle, but there are some important differences:
Activity Life Cycle: The activity life cycle consists of methods such as onCreate(), onStart(), onResume(), onPause(), onStop(), and onDestroy(). These methods are called on the activity itself.
Fragment Life Cycle: The fragment life cycle consists of methods such as onAttach(), onCreate(), onCreateView(), onActivityCreated(), onStart(), onResume(), onPause(), onStop(), onDestroyView(), onDestroy(), and onDetach(). These methods are called on the fragment itself.
The main difference is that the fragment life cycle is tied to the activity life cycle. When an activity goes through its life cycle, it also triggers corresponding methods in its fragments. For example, when an activity's onStart() method is called, it also triggers the onStart() method of all its fragments.
Another difference is that fragments have their own UI and can be added or removed dynamically from an activity. This allows for more flexible and modular UI designs.
Follow-up 2
What is the role of the onAttach() method in the fragment life cycle?
The onAttach() method is called when the fragment is attached to its hosting activity. Its main role is to initialize any communication between the fragment and the activity. This method is typically used to get a reference to the hosting activity and set up any necessary callbacks or listeners.
For example, in the onAttach() method, you can cast the activity parameter to the appropriate interface and store it in a member variable. This allows the fragment to communicate with the activity by calling methods defined in the interface.
Here is an example of how the onAttach() method can be implemented:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MyFragmentListener) {
mListener = (MyFragmentListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement MyFragmentListener");
}
}
Follow-up 3
What happens when a fragment is in the onDetach() state?
When a fragment is in the onDetach() state, it means that it has been detached from its hosting activity. This can happen when the activity is destroyed or when the fragment is removed from the activity dynamically.
In the onDetach() state, the fragment is no longer associated with any activity and cannot access the activity's resources or perform any UI-related operations. Any references to the activity should be cleared to avoid memory leaks.
The onDetach() method is typically used to clean up any communication between the fragment and the activity. For example, you can set any callbacks or listeners to null and release any references to the activity.
Here is an example of how the onDetach() method can be implemented:
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
Follow-up 4
What is the difference between onActivityCreated() and onStart() in the fragment life cycle?
The onActivityCreated() and onStart() methods are both part of the fragment life cycle, but they serve different purposes:
onActivityCreated(): This method is called when the activity's onCreate() method has returned. It is typically used to initialize the fragment's UI and restore any saved state. This is a good place to set up any UI-related operations that require the activity to be fully created.
onStart(): This method is called when the fragment becomes visible to the user. It is used to start any animations or other visual effects. This is a good place to start any operations that are not dependent on the activity's full creation.
In summary, onActivityCreated() is called after the activity's onCreate() method and is used for UI initialization, while onStart() is called when the fragment becomes visible and is used for starting visual effects or animations.
Here is an example of how the onActivityCreated() and onStart() methods can be implemented:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Initialize UI and restore saved state
}
@Override
public void onStart() {
super.onStart();
// Start animations or other visual effects
}
4. What is a service in Android and how does its life cycle work?
A Service is an Android application component that runs in the background without a user interface. It is suited for operations that need to continue while the user is not actively interacting with your app — playing music, downloading files, syncing data, or maintaining a network connection.
Types of services
- Started service (
startService/startForegroundService): runs until it stops itself (stopSelf()) or another component stops it. From Android 8+ (Oreo), background started services are heavily restricted and will be killed shortly after the app goes to the background. UsestartForegroundService()and callstartForeground()within 5 seconds to show a persistent notification, or useWorkManagerfor deferrable background work. - Bound service (
bindService): provides a client-server interface to components that bind to it. Runs only as long as at least one component is bound. Useful for IPC or for exposing APIs to other app components. - Foreground service: a started service that has called
startForeground()to display a notification. The system treats it at a higher priority and will not kill it under normal memory pressure. Required for ongoing user-visible tasks (music playback, navigation, location tracking).
Service life cycle callbacks
For a started service:
onCreate(): one-time initialization.onStartCommand(intent, flags, startId): called each timestartService()is called. Return value controls restart behavior:START_STICKY(restart with null intent),START_NOT_STICKY(don't restart),START_REDELIVER_INTENT(restart with original intent).onDestroy(): cleanup.
For a bound service:
onCreate(): one-time initialization.onBind(intent): return anIBinderinterface for clients.onUnbind(intent): all clients have unbound.onDestroy(): cleanup.
Modern background work recommendations
| Use case | Recommended API |
|---|---|
| Deferrable, guaranteed work (sync, upload) | WorkManager |
| User-visible ongoing work (music, navigation) | Foreground Service |
| Coroutine-based async work in a component | viewModelScope / lifecycleScope |
| Periodic work | WorkManager with PeriodicWorkRequest |
Common gotchas
- Services run on the main thread by default. Long-running work must be moved to a coroutine (
CoroutineScope) or a separate thread.IntentServicewas the old way; it is deprecated — useWorkManageror aCoroutineWorkerinstead. - From Android 14, foreground service types (
dataSync,mediaPlayback,location, etc.) must be declared explicitly in the manifest and require corresponding permissions. - A bound service is not destroyed when all clients unbind if it was also started — you must stop it explicitly.
Follow-up 1
What is the difference between a started service and a bound service?
A started service is a service that is explicitly started by calling the startService() method. It continues to run until it is explicitly stopped by calling the stopService() method or until it stops itself by calling the stopSelf() method. A started service does not have a direct connection with the component that started it.
A bound service is a service that is bound to a component by calling the bindService() method. It provides a client-server interface, allowing the component to interact with the service. The service remains active as long as there are clients bound to it. When all clients unbind from the service, the service is destroyed.
Follow-up 2
What is the role of the onBind() method in the service life cycle?
The onBind() method is a callback method in the service life cycle that is called when a component binds to the service by calling the bindService() method. It returns an IBinder object that provides a communication channel between the component and the service. The onBind() method must be implemented in a bound service, and it is responsible for returning the IBinder object that the client can use to interact with the service.
Follow-up 3
What happens when a service enters the onDestroy() state?
When a service enters the onDestroy() state, it means that the service is being stopped or destroyed. This can happen when the service is explicitly stopped by calling the stopService() method, when the service stops itself by calling the stopSelf() method, or when the system destroys the service to reclaim resources.
In the onDestroy() method, you can perform any necessary cleanup or release any resources that the service has acquired during its lifetime.
Follow-up 4
What is the difference between onStartCommand() and onBind() in the service life cycle?
The onStartCommand() method is a callback method in the service life cycle that is called when a component starts the service by calling the startService() method. It is used for services that are started and run independently of any other component. The onStartCommand() method receives an Intent object that contains the command to be executed by the service.
The onBind() method, on the other hand, is called when a component binds to the service by calling the bindService() method. It is used for services that provide a client-server interface and need to interact with the component that bound to them. The onBind() method returns an IBinder object that provides the communication channel between the component and the service.
5. What is the difference between an activity and a service in Android?
An Activity and a Service are both Android application components, but they serve fundamentally different purposes.
Activity
- Has a user interface — it is a screen the user interacts with.
- Lives while the user is navigating your app's UI. The system can recreate it on configuration changes (rotation, locale change).
- Has a complex life cycle (
onCreate→onStart→onResume→onPause→onStop→onDestroy) tied to visibility and user focus. - Runs on the main thread; UI updates happen here.
- In modern Android, Jetpack Compose composables are hosted inside an Activity and handle individual screens.
Service
- Has no user interface.
- Designed to run in the background — either while the user is in a different app or when the screen is off.
- Simple life cycle: started services have
onCreate/onStartCommand/onDestroy; bound services additionally useonBind/onUnbind. - Also runs on the main thread by default — long-running work must be dispatched to a coroutine or worker thread.
- Must call
startForeground()with a notification (a foreground service) if it needs to survive Android 8+'s background execution limits.
Key differences at a glance
| Activity | Service | |
|---|---|---|
| UI | Yes | No |
| Trigger | User navigation, Intent | startService() / bindService() |
| Life cycle tied to | Visibility / user interaction | Start/stop/binding |
| Survives app in background | No (can be killed) | Foreground service yes; background service no (from Android 8+) |
| Modern replacement | Compose NavHost screen |
WorkManager, foreground service |
Interplay between them
An Activity can start a Service (e.g., kicking off a download), bind to it to get progress updates, or receive a broadcast from it. In practice, many patterns that used Services for background work are now handled by WorkManager (for guaranteed deferred work) or by viewModelScope coroutines (for work tied to a ViewModel's lifetime), reducing the need for Services in everyday apps.
Follow-up 1
Can a service run in the background indefinitely?
By default, a service runs on the main thread of the application and can be terminated by the system if it needs resources. However, you can create a foreground service that has a higher priority and is less likely to be killed by the system. A foreground service must display a persistent notification to the user, indicating that it is running in the background.
Follow-up 2
How does the system manage the life cycle of a service?
The system manages the life cycle of a service by calling specific methods at different stages. When a service is started, the system calls the onCreate() method to initialize the service. Then, it calls the onStartCommand() method to start the service's execution. The service can run indefinitely or stop itself by calling the stopSelf() method. When the service is no longer needed, the system calls the onDestroy() method to clean up any resources used by the service.
Follow-up 3
Can you give an example of when you would use a service instead of an activity?
One example of when you would use a service instead of an activity is when you need to perform a long-running operation in the background, such as downloading a large file or playing music. In these cases, you can use a service to handle the operation without blocking the user interface of the application. The service can continue running even if the user switches to a different activity or exits the application.
Follow-up 4
What are the potential issues with using a service in Android?
There are a few potential issues to consider when using a service in Android. One issue is that a service runs on the main thread by default, which can cause performance issues if the service performs heavy tasks. To avoid this, you can use a separate thread or an AsyncTask to perform the task in the background. Another issue is that a service can consume a significant amount of system resources if not managed properly, which can lead to battery drain or performance degradation. It is important to design the service efficiently and release any acquired resources when they are no longer needed.
Live mock interview
Mock interview: Android Basics
- Read your scene and goals
- Talk it out; goals tick off live
- Get a score and stronger lines
Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.