Android Development

    20 Android interview questions that keep coming up Interviews

    A
    AzeemNov 3, 2026 · 16 min read
    36

    Interviewers rarely stop after the first question. They may ask what a coroutine is, then why it is cheaper than a thread, then what happens when you cancel it. The first answer gets you into the conversation. The follow-ups decide how it ends.

    I’m Azim Siddiqui, an Android engineer and founder of TheCodingShef. I have built production apps at Blinkit, BatterySmart, ShareChat and Nagarro, and I mentor Android developers preparing for interviews. Below are 20 questions that keep coming up, each with a simple answer you can build on.

    Lifecycle and components

    1. What is the difference between onCreate(), onStart(), and onResume()?

    They answer three different questions about an Activity.

    • onCreate() means the Activity instance is being created. Android calls it once for each Activity instance. This is where you usually set up the layout, ViewModel, bindings and initial configuration.

    • onStart() means the Activity has become visible to the user, but the user may not be able to interact with it yet.

    • onResume() means the Activity is in the foreground and the user can interact with it.

    onStart() and onResume() can run many times for the same Activity. For example, if the user opens another app and comes back, the Activity may go through onRestart(), onStart() and onResume() again, but not onCreate().

    Follow-up: What runs when the user opens a dialog over your Activity?

    2. What is the difference between the Fragment lifecycle and the Fragment view lifecycle?

    A Fragment has two connected lifecycles.

    The Fragment lifecycle runs from onCreate() to onDestroy(). It represents the Fragment object itself.

    The view lifecycle runs from onCreateView() to onDestroyView(). It represents the Fragment’s UI. This view lifecycle can repeat many times inside one Fragment lifecycle, especially when the Fragment is added to the back stack and then comes back.

    Most Fragment UI bugs happen when developers tie UI work to the Fragment lifecycle instead of the view lifecycle. For example, if you collect a Flow using the Fragment lifecycle but the view is destroyed, you may try to update a view that no longer exists.

    That is why UI-related observers should usually use viewLifecycleOwner.

    Follow-up: Why does a Fragment leak its binding if you never set it to null?

    3. What are Android launch modes?

    Launch modes control whether starting an Activity creates a new instance or reuses an existing one.

    • standard: Every launch creates a new instance of the Activity, even if one already exists.
      Example: Opening a product details screen again creates another product screen.

    • singleTop: If the Activity is already at the top of the task, Android reuses it and sends the new Intent to onNewIntent(). If it is not on top, a new instance is created.
      Example: A search screen at the top receives a new search Intent; instead of opening a new search screen, Android reuses the same screen.

    • singleTask: Only one instance exists in its task. If it already exists, Android brings it to the front and removes Activities above it.
      Example: Tapping a notification opens the app’s home screen; if home is already open, Android brings it forward instead of creating another home screen.

    • DsingleInstance: The Activity stays alone in its own task. No other Activity can be added to that task.
      Example: A separate browser or payment Activity that should remain isolated from the rest of the app.

    Follow-up: What do you have to handle when you use singleTop?
    You must override onNewIntent() and update the UI or state using the new Intent, because onCreate() will not run again.

    Follow-up: What do you have to handle when you use singleTop?

    4. What is the difference between Application context and Activity context?

    Application context lives as long as the app process. Activity context lives only as long as that Activity.

    Use Activity context for things connected to the UI, such as showing a dialog, inflating a layout with the correct theme, or starting another Activity.

    Use Application context for long-lived objects, such as a singleton, database, repository or dependency-injection container. This avoids keeping a reference to an Activity after it is destroyed.

    A static field holding an Activity is dangerous because the Activity cannot be garbage-collected even after the user leaves the screen. That creates a memory leak.

    Follow-up: Why does a static field holding an Activity cause a leak?

    Kotlin coroutines and Flow

    5. What is the difference between cold flows and hot flows?

    A cold Flow does nothing until someone collects it. Each collector starts its own execution from the beginning.

    For example, if you create a Flow using flow { }, it will not run until collect() is called. If two collectors collect it, the Flow runs twice.

    A hot Flow is already active and can emit values even when no one is collecting it. All collectors share the same stream.

    StateFlow and SharedFlow are hot flows. StateFlow always holds the latest value, while SharedFlow can replay past values and emit events to multiple collectors.

    One way to remember it: a cold Flow is a recipe cooked separately for each person. A hot Flow is a broadcast that everyone listens to.

    Follow-up: How do you turn a cold flow into a StateFlow?

    6. Which coroutine scopes are available in Android, and why avoid GlobalScope?

    Use coroutine scopes tied to a lifecycle so the work is cancelled when its owner is gone.

    • viewModelScope: Use it inside a ViewModel. Work is cancelled when the ViewModel is cleared.

    • lifecycleScope: Use it in an Activity or Fragment. Work is cancelled when the lifecycle is destroyed.

    • repeatOnLifecycle: Useful when collecting Flows only while the UI is started or resumed.

    • rememberCoroutineScope: Use it in Compose to launch coroutines from user events.

    Avoid GlobalScope because it is not tied to any lifecycle. A coroutine launched in GlobalScope can keep running even after the screen is closed, the ViewModel is cleared, or the user leaves the app. That can waste resources and cause leaks.

    Follow-up: What if the work has to outlive the screen?

    7. Why can we create many coroutines but not millions of threads?

    A thread is managed by the operating system. Each thread needs real memory for its stack and takes kernel resources for scheduling. Creating too many threads can exhaust memory and make the system slow.

    A coroutine is managed by the Kotlin runtime. It is much lighter than a thread. When a coroutine is suspended, it does not hold a thread. The thread becomes free to run other coroutines.

    So, one thread can run many coroutines by switching between them whenever one coroutine waits for something, such as a network response or database operation.

    Follow-up: What happens to the thread while a coroutine is suspended?

    Jetpack Compose and UI

    8. How do you retain state across recompositions and configuration changes?

    Choose the storage based on how long the state needs to live.

    • remember: Survives recomposition, but not configuration changes.

    • rememberSaveable: Survives configuration changes and process death, if the value can be saved in a Bundle.

    • ViewModel: Survives configuration changes, such as screen rotation.

    • Room, DataStore or SharedPreferences: Survives app restarts.

    Keep each piece of state in the smallest place that is enough for its lifetime.

    For example, use rememberSaveable for a selected tab, ViewModel for a list loaded from an API, and DataStore for a user preference such as dark mode.

    Follow-up: Why is a ViewModel not enough after process death?

    9. What is the difference between LaunchedEffect and rememberCoroutineScope?

    LaunchedEffect starts a coroutine when a Composable enters the composition or when its key changes.

    Use it for work that should happen because the screen appeared. For example, collecting a ViewModel state or calling a one-time analytics event.

    rememberCoroutineScope gives you a coroutine scope that you can use to launch work in response to an event, such as a button click.

    Both are cancelled when the Composable leaves the composition. The difference is who starts the work: LaunchedEffect starts it based on composition, while rememberCoroutineScope starts it when you decide, usually after a user action.

    Follow-up: What happens to a LaunchedEffect when its key changes?

    10. Why should you provide keys in LazyColumn items?

    A key gives each item a stable identity based on data, not position.

    Without keys, Compose identifies items by their index. If you insert an item at the top, every item shifts position. Compose may think the item at position 0 changed, even though it is actually a new item.

    With keys, Compose knows that the item with id = 10 is still the same item, even if its position changes. This helps preserve item state, scroll position and animations.

    A good key is stable, unique and based on the item itself, such as a database ID. Avoid using list index or hashCode() as a key. Also, two items must not have the same key, because that can cause runtime issues.

    Follow-up: What makes a good key, and what happens if two items share one?

    Stop for a minute and check yourself

    Be honest about the first 10. Could you give the short answer, and then the follow-up, without hesitating?

    If the answers came easily, good. If the follow-ups made you pause, that is not a knowledge problem. It is a depth problem, and it is the most common reason strong developers lose interviews. They use Coroutines, Compose and MVVM every day, but they have never had to explain the internals out loud.

    There are two ways I help with that.

    1. Study it yourself: the book.
    Endgame: Android Interviews has 523 answers across 31 chapters. Every answer has the short version you can say in the interview, the deeper explanation, the common mistakes and the follow-ups the interviewer asks next. It has 123 diagrams, it is web based, and future updates are included. There is a free sample on the page so you can judge the depth before you buy.
    https://thecodingshef.in/books/endgame-android-interviews
    Use code [LAUNCH CODE] at checkout for the launch discount.

    2. Get guided: the Android Job Ready Bootcamp.
    If you have 2 or more years of experience and want a mentor, this is the next step: live deep-dive sessions on Coroutines, Flow, Compose internals, architecture and Android system design (HLD and LLD), plus machine coding, assignments, mock interviews and resume review. I have mentored 500+ developers and run hundreds of Android mock interviews. The bootcamp is built around the gaps I see in those interviews.
    It is for developers who already know Kotlin and have built real Android apps. It is not for complete beginners.
    https://thecodingshef.in/course/master-android

    If you are not sure which fits, start with the book. It is the faster and cheaper way to find out where your gaps are.

    Now, the remaining 10 questions.

    Data, background work and architecture

    11. How does DiffUtil improve RecyclerView performance?

    DiffUtil compares the old list with the new list and finds the smallest set of changes: insertions, removals, moves and updates.

    Instead of calling notifyDataSetChanged(), which tells RecyclerView that everything may have changed, DiffUtil lets RecyclerView update only the affected rows. This saves work and enables better animations.

    DiffUtil uses two main methods:

    • areItemsTheSame(): Checks whether two items represent the same object, usually by comparing IDs.

    • areContentsTheSame(): Checks whether the visible data of the same item has changed.

    For large lists, you can calculate the diff on a background thread using AsyncListDiffer or ListAdapter.

    Follow-up: What is the difference between areItemsTheSame and areContentsTheSame?

    12. What are Room migrations, and how do you implement them?

    A Room migration moves an existing database from one schema version to the next without deleting the user’s data.

    For example, if version 1 has a users table and version 2 adds an email column, you need a migration that runs an SQL statement to add that column.

    The steps are:

    • Change the entity.

    • Increase the database version.

    • Write a Migration object with the required SQL.

    • Add the migration to the Room database builder.

    Room also supports auto migrations for simpler changes, such as adding a column or table, when you provide the proper schema information.

    Without a migration, Room cannot open the old database and the app can crash.

    Follow-up: Why is fallbackToDestructiveMigration() dangerous in production?

    13. When should you use WorkManager instead of a Service?

    Use WorkManager for deferrable background work that should still run even if the app closes or the device restarts.

    Examples include syncing data, uploading logs, compressing images, or cleaning old cached files. WorkManager can also add constraints such as requiring network, charging, or enough storage.

    Use a Service when the work needs to happen immediately and the user is aware of it. For example, music playback or an active navigation session.

    WorkManager is for work that can wait but must not be lost. A Service is for immediate, user-facing work.

    Follow-up: Which constraints can you set on a work request?

    14. What is Doze mode, and how does it affect your app?

    Doze is a battery-saving state. Android enters it when the device is unplugged, stationary, and the screen has been off for some time.

    In Doze, Android restricts background work to save battery. It can delay network access, jobs, syncs and standard alarms. Wake locks may also be ignored.

    The system briefly allows maintenance windows, during which pending jobs, syncs and alarms can run. After that, the device returns to Doze.

    When the user moves the device, turns on the screen, or plugs in the charger, the device exits Doze and normal background activity resumes.

    Follow-up: How do you deliver a time-critical notification during Doze?

    15. Compare MVC, MVP, MVVM and MVI.

    All four patterns separate UI from business logic and data. They differ in how the UI and logic communicate.

    • MVC: The Controller handles input and updates the Model and View. On Android, Activities and Fragments often end up doing too much.

    • MVP: The Presenter contains presentation logic and talks to a passive View through an interface.

    • MVVM: The ViewModel exposes state, and the View observes it. This works well with Jetpack and lifecycle-aware components.

    • MVI: The UI sends intents or events, the state is immutable, and the UI renders from a single state object. This makes state changes easier to trace.

    MVVM became common on Android because ViewModels survive configuration changes and work naturally with LiveData and Flow. MVI adds stricter state management, which helps in complex screens.

    Follow-up: Why did MVVM replace MVP on Android?

    Internals, performance and security

    16. What are Looper, Handler and MessageQueue, and how do they work together?

    They are the building blocks of Android’s message-based threading system.

    • MessageQueue holds messages and runnable tasks waiting to execute.

    • Looper continuously takes items from the queue and executes them one by one.

    • Handler lets you send messages or post tasks to a thread’s queue.

    A thread can have only one Looper and one MessageQueue, but it can have many Handlers.

    The main thread already has a Looper. That is why UI updates happen on the main thread. If you block the main thread for too long, it cannot process input, drawing or lifecycle messages, which can cause an ANR.

    Follow-up: Why does blocking the main thread cause an ANR?

    17. What is Binder, and how does inter-process communication work on Android?

    Binder is Android’s main inter-process communication mechanism, or IPC.

    Android apps usually run in separate processes for security and stability. Binder lets one process call methods in another process as if it were a local call.

    When a client calls a remote method, the arguments are converted into a Parcel. The Binder driver sends that Parcel to the target process. The call runs on a Binder thread there, and the result is sent back in the same way.

    You see Binder in many Android features, such as talking to system services, using AIDL, or communicating with another app through a bound Service.

    Follow-up: Why is there a size limit on what you can send through Binder?

    18. What causes jank, and how do you detect dropped frames?

    Jank is a visible stutter or freeze in the UI. It happens when a frame is not ready before the screen needs to display it.

    At 60 Hz, the display refreshes every 16.7 milliseconds. At 120 Hz, the target is about 8.3 milliseconds. In that time, Android must handle input, animation, layout, drawing and GPU work.

    If the main thread or render thread takes too long, the frame is delayed or dropped, and the user sees jank.

    You can detect it using JankStats, Macrobenchmark with FrameTimingMetric, Profile GPU Rendering, and system traces. Once you find a slow frame, use the trace to identify whether the problem is in layout, drawing, recomposition, image loading, or main-thread work.

    Follow-up: How would you find which Composable or view causes it?

    19. What is SSL pinning, and why is it important?

    SSL pinning means your app accepts only a specific certificate or public key for your server.

    Normally, Android trusts certificates signed by trusted certificate authorities. If an attacker gets a fraudulent certificate from a compromised or malicious CA, they may be able to intercept traffic.

    With pinning, the app checks that the server’s certificate or public key matches the expected pin. If it does not match, the connection fails.

    This improves protection against man-in-the-middle attacks, but it needs careful handling. If the server certificate changes and the app still has the old pin, legitimate users may lose connectivity until the app is updated.

    Follow-up: What happens to your app when the server rotates its certificate?

    20. How does the Android Keystore protect keys?

    Android Keystore stores cryptographic keys in a protected container so they are difficult to extract from the device.

    Your app does not directly access the raw key. Instead, it asks the system to encrypt, decrypt or sign data. The system performs the operation and returns the result.

    On supported devices, the key material can stay inside secure hardware such as the TEE or StrongBox. StrongBox is a separate secure element and is more resistant to hardware attacks.

    You can also require user authentication before a key can be used. This means the key can be used only after the user verifies themselves with a PIN, pattern, password or biometric authentication.

    Follow-up: What happens to a Keystore key when the user changes their lock screen?

    Was this helpful?

    Comments (0)

    No comments yet. Be the first to share your thoughts!

    Leave a Comment

    Get the latest updates

    Join our newsletter and never miss an article.

    By subscribing, you agree to our Privacy Policy and consent to receive updates.

    Ready to Start Learning?

    Join thousands of students building their dream careers

    Explore Courses