Free Android Architecture Interview Questions & Answers

MVVM/MVI, unidirectional data flow, state modeling, and scalable app structure.

All 50 questions and detailed answers are free. No account or sign-in required.

  1. What is unidirectional data flow (UDF) and what specifically makes it 'unidirectional'?

    In UDF, state flows down from a single owner (typically the ViewModel) to the UI, and events flow up from the UI back to that owner, which is the only thing allowed to mutate state. The UI never mutates its own state directly; it only requests changes by emitting events. This is what makes it unidirectional: there is exactly one path for state to change, so you always know where a value came from and where it can be modified, which makes bugs reproducible and testable.

  2. Why expose a StateFlow via asStateFlow() instead of just returning the MutableStateFlow?

    The pattern is a private MutableStateFlow backing field and a public read-only StateFlow exposed through asStateFlow(). If you expose the mutable one directly, any collector could cast it back to MutableStateFlow and call value assignment or update() from outside the ViewModel, breaking the single-source-of-truth guarantee. asStateFlow() returns a read-only wrapper that cannot be cast back to the mutable type, so mutation stays confined to the ViewModel. It is about enforcing an API boundary, not about thread safety.

  3. What is the single source of truth principle and how does it fail in practice?

    Single source of truth means every piece of data has exactly one authoritative owner, and everything else derives or observes from it rather than keeping its own copy. It commonly fails when a screen caches a value locally, such as a copy of the user in a fragment field, that then drifts out of sync with the ViewModel or repository after an update. The fix is to always read from the one owner and derive everything downstream, so an update in one place is automatically reflected everywhere without manual synchronization.

  4. What is the core difference between MVVM and MVP?

    In MVP the presenter holds a reference to the view through an interface and imperatively calls methods on it like showLoading() or showError(), so it pushes changes to a passive view. In MVVM the ViewModel exposes observable state and has no reference to the view at all; the view observes and reacts. The practical consequence is that the ViewModel is far easier to unit test because it has no view dependency, and it survives configuration changes, whereas a presenter is usually recreated with its view.

  5. How does MVI differ from plain MVVM, and what problem does it solve?

    MVI keeps UDF but adds two constraints: the entire screen state is modeled as one immutable object, and all user actions are funneled through a single entry point, often called an intent or event, that produces a new state via a reducer. Plain MVVM often exposes several independent LiveData or StateFlow fields that can be updated in inconsistent combinations. MVI's single-state, single-reducer discipline makes illegal state combinations harder to represent and makes every state transition explicit and traceable, at the cost of more boilerplate.

  6. When would you choose a single sealed UiState versus a data class with independent fields?

    A sealed UiState with Loading, Success, and Error subtypes is best when the states are truly mutually exclusive and each carries different data, because the type system then prevents you from rendering data that does not exist in that state. A data class with independent boolean and nullable fields is better when a screen can legitimately show multiple things at once, such as cached content visible while a refresh spinner runs and an error banner appears. The trap is forcing mutually-inclusive UI into a sealed class, which forces you to duplicate the shared data across subtypes.

  7. Why can a sealed UiState of Loading, Success, Error make swipe-to-refresh awkward?

    With strict Loading, Success, and Error subtypes, entering Loading during a refresh means you no longer hold the already-loaded data, so the screen flashes a full-screen spinner over content the user was already viewing. The states are modeled as exclusive when in reality refreshing while showing existing data is a valid combination. The fix is usually a data class where isRefreshing is a separate flag alongside the data list, so the existing content stays on screen while the refresh indicator shows on top.

  8. What is the difference between surviving a configuration change and surviving process death?

    A configuration change like rotation destroys and recreates the Activity, but the ViewModel instance is retained in memory by the ViewModelStore, so its in-memory fields survive automatically. Process death happens when the OS reclaims your backgrounded app's process entirely; the ViewModel and all in-memory state are gone, and on return the system recreates everything from scratch. Only data saved to SavedStateHandle or persistent storage survives process death, so relying on plain ViewModel fields for critical state is a common bug that only appears under memory pressure.

  9. What belongs in SavedStateHandle and what does not?

    SavedStateHandle is for small, transient UI state that must survive process death, such as a search query, a selected tab, or a scroll position, and it is backed by the saved instance state Bundle so it has a size limit and must hold only parcelable data. It is not a cache for large lists or network results; those should come from the repository, which reloads them from disk or network after process death. Putting big objects or entire screen models into SavedStateHandle risks TransactionTooLargeException and abuses a mechanism meant for tiny reconstruction hints.

  10. Why is exposing one-off events like navigation or a toast as StateFlow state considered an antipattern?

    StateFlow holds a current value and re-emits it to every new collector, so if you model a one-off event like show snackbar as StateFlow state, it will fire again after a configuration change when the UI re-subscribes and reads the retained value. That produces duplicate toasts or repeated navigation. The problem is a category error: one-off events are not state, they have no meaningful current value, so representing them with a value-holding stream inherently causes replays.

  11. Why can a SharedFlow with replay 0 silently drop one-off events?

    A MutableSharedFlow with replay 0 and no extra buffer emits only to collectors that are actively subscribed at the moment of emission; there is no stored value. If the ViewModel emits a navigation event while the UI is in the background and has stopped collecting, for example collection tied to the STARTED lifecycle, the event has nowhere to go and is lost. This is the classic missed-event bug, and it is why an unbuffered SharedFlow is a risky vehicle for events that must not be dropped.

  12. Why is a Channel with receiveAsFlow() often the recommended tool for one-off events?

    A Channel buffers emitted events and, crucially, guarantees each event is delivered to exactly one collector and is not replayed, so when the UI stops collecting the events queue up and are delivered once it resumes. Exposing it via receiveAsFlow() gives a cold flow where a suspended send waits rather than silently dropping. This solves both problems of the StateFlow approach, no replay, and the unbuffered SharedFlow approach, no loss while backgrounded, which is why it became the common idiom for events that must fire exactly once.

  13. What is the modern state-based events argument that says you often do not need an event channel at all?

    The argument, promoted in recent Android guidance, is that many things treated as one-off events are actually state. Instead of firing a show error event, you put an error message in the UiState; the UI shows it and then calls a ViewModel method to clear it once consumed, so consumption itself becomes a state transition. This keeps everything in the single UDF state stream, survives configuration changes correctly, and avoids the entire event-delivery reliability problem. It does not fit everything, since true navigation is often still an event, but it removes most cases.

  14. What is the repository pattern actually responsible for, and where is its boundary?

    A repository owns the decision of where data comes from and mediates between data sources, deciding whether to serve from cache, database, or network and returning domain models rather than raw DTOs. Its boundary is data access and reconciliation; it should not contain UI logic, Android framework types, or business rules about how features behave. A common smell is a repository that takes a Context, formats strings for display, or makes navigation decisions, which means responsibilities from other layers have leaked into it.

  15. When are use cases or interactors genuinely useful, and when are they just ceremony?

    A use case earns its place when it encapsulates real business logic that is shared across multiple ViewModels, combines several repositories, or expresses a meaningful domain operation that you want to test in isolation. It becomes ceremony when it is a one-line pass-through that simply calls repository getX and adds nothing, because then you have an extra file, an extra injection, and indirection for zero behavior. The pragmatic rule is to add use cases when logic is shared or non-trivial, not as a blanket mandate for every repository call.

  16. State the dependency rule of Clean Architecture and how it maps to Android layers.

    The dependency rule says source-code dependencies point only inward toward higher-level policy: the domain layer at the center depends on nothing, while data and presentation layers depend on domain, never the reverse. In Android this means the domain layer defines repository interfaces and pure domain models, the data layer implements those interfaces, and the presentation layer of ViewModels depends on domain. The domain must not import Android framework types, Retrofit, or Room; if it does, the rule is violated and the layering is only cosmetic.

  17. Why keep separate domain models, network DTOs, and UI models instead of one shared class?

    Each model answers to a different owner: the DTO mirrors the server's JSON contract and changes when the API changes, the domain model expresses your business concepts, and the UI model is shaped for display, sometimes with preformatted strings. Sharing one class couples all three, so a server field rename ripples into your UI and a display tweak pressures your network parsing. The cost is mapping code, but that mapping is exactly the insulation that lets each layer evolve independently, and it centralizes handling of nulls and defaults at the boundary.

  18. What does dependency inversion mean concretely for a ViewModel that needs data?

    Dependency inversion means the ViewModel depends on an abstraction it owns or that lives in the domain layer, such as a UserRepository interface, not on a concrete class like UserRepositoryImpl that knows about Retrofit and Room. The concrete implementation depends on that interface, so the arrow is inverted: the low-level detail depends on the high-level policy. Practically this lets you inject a fake implementation in tests and swap data sources without touching the ViewModel, and it is what makes the layer boundary real rather than a naming convention.

  19. How do you recognize a god ViewModel and how do you split it?

    A god ViewModel accumulates unrelated responsibilities: it drives several screens or sections, holds dozens of state fields, mixes multiple features, and grows hundreds of lines with logic that has no reason to change together. You split it by cohesion, typically one ViewModel per screen or per clearly bounded sub-feature, extracting shared business logic into use cases and shared data access into repositories rather than duplicating. The heuristic is the single-responsibility one: if two parts of the ViewModel would change for entirely different reasons, they belong apart.

  20. How do you properly test a ViewModel that launches coroutines, and why does TestDispatcher matter?

    You inject a fake repository so you control the returned data, and you replace the coroutine dispatcher with a TestDispatcher, via Dispatchers.setMain or by injecting a dispatcher, so the test scheduler controls virtual time. This lets you advance time deterministically and assert on emitted states without real delays or flakiness. Without a TestDispatcher, coroutines may run on a real background thread and your assertions race against them; the TestDispatcher makes execution synchronous and ordered so tests are reliable.

  21. Why should a ViewModel not reference Dispatchers.IO directly, and what should it do instead?

    Hardcoding Dispatchers.IO makes the code untestable in a controlled way, because a test cannot substitute a TestDispatcher for it, and it scatters threading decisions across the codebase. The better practice is to inject a dispatcher, or a small dispatcher-provider abstraction, so tests pass a TestDispatcher and production passes the real one. Even better, push the withContext to the layer that actually does IO, so the ViewModel stays dispatcher-agnostic and simply calls suspend functions that are already main-safe.

  22. What does main-safe mean for a suspend function and whose responsibility is it?

    A main-safe suspend function is one that is safe to call from the main thread because it internally moves any blocking or CPU-heavy work off the main thread using withContext, so the caller never has to think about dispatchers. The responsibility belongs to the function doing the work, typically the repository or data source, not the ViewModel. This inverts the older pattern of the ViewModel wrapping every call in withContext, keeping the ViewModel clean and preventing accidental main-thread blocking when a caller forgets to switch context.

  23. In offline-first design, what is the key architectural decision about the source of truth?

    The central decision is that the local database, not the network, is the single source of truth: the UI observes the database, and the network is treated as just another way to update that database. Writes and reads go through the local store, and a sync process reconciles it with the server in the background. This means the app renders instantly from cache, works without connectivity, and avoids the bug where UI reads sometimes from cache and sometimes from network and shows inconsistent data depending on timing.

  24. Who should own caching strategy, and why is caching in the ViewModel a smell?

    Caching belongs to the data layer, specifically the repository, because it is a data-access concern about where and how long to keep data, and the ViewModel should be oblivious to whether a value came from memory, disk, or network. If a ViewModel holds its own cache, that cache is lost on process death, is duplicated across ViewModels that need the same data, and mixes UI-lifecycle concerns with persistence. Centralizing it in the repository gives one place to invalidate, one place to reason about freshness, and correct behavior across the whole app.

  25. What is the state down, events up principle in Compose and how does it shape composable APIs?

    State flows down as parameters into composables and events flow up as lambda callbacks, so a well-designed composable receives its data and exposes onClick-style callbacks rather than reaching into a ViewModel itself. This is the stateless, or state-hoisted, pattern: the composable becomes a pure function of its inputs, easy to preview and test, while the stateful owner, a screen-level composable holding the ViewModel, wires state and events together. Mixing the two, by having leaf composables grab ViewModels, reintroduces hidden dependencies and hurts reusability and preview support.

  26. How does the choice between Compose and the View system actually affect app architecture?

    The core architecture, UDF, single source of truth, ViewModel-owned state, repositories, is the same for both because those are UI-toolkit-agnostic. The difference is at the boundary: Compose consumes state declaratively via collectAsStateWithLifecycle and recomposes, so it pushes you toward immutable state and away from imperative view mutation, whereas the View system needs observers that imperatively update widgets. Compose makes state hoisting natural and reduces the temptation to store UI state in view fields, but it does not change where your business logic or data ownership lives.

  27. Why is collectAsStateWithLifecycle preferred over collectAsState in Compose?

    Plain collectAsState keeps collecting the flow even when the app is in the background, so it continues doing work and holding upstream active while the screen is not visible, wasting resources and potentially processing updates no one sees. collectAsStateWithLifecycle ties collection to the lifecycle, pausing at STOPPED and resuming at STARTED, which matches the platform's visibility semantics. It became the recommended default precisely because the naive version leaks work off-screen, though you must ensure the upstream flow can handle stopping and restarting collection.

  28. What is the danger of combining several independent StateFlows into UI state incorrectly, and how does combine help?

    If a screen exposes separate flows for data, loading, and error and the UI reads them independently, the UI can momentarily observe an inconsistent mix, such as loading false but data still empty, producing a flicker or wrong render. Using combine to merge the sources into one derived UiState guarantees the UI only ever sees a coherent snapshot where all fields were computed together. The subtlety is that combine only emits after every source has emitted at least once, so you must give each an initial value or the combined state will not appear.

  29. What does stateIn do and why do WhileSubscribed timeouts matter for it?

    stateIn converts a cold flow into a hot StateFlow with an initial value, sharing one upstream collection among all subscribers so the underlying work runs once. Its sharing policy governs when the upstream is active: WhileSubscribed with a 5000 millisecond timeout keeps it alive for five seconds after the last subscriber leaves, which is exactly long enough to survive a configuration change without restarting the flow, while still stopping work when the user truly leaves. Using Eagerly or Lazily instead keeps the upstream running forever, and a zero timeout restarts work on every rotation.

  30. Where should mapping between DTO and domain model happen, and what breaks if it happens in the ViewModel?

    Mapping belongs at the data-layer boundary, inside the repository or a dedicated mapper it calls, so that everything above the repository deals only in clean domain models. If the ViewModel receives raw DTOs and maps them, then Retrofit or JSON annotations leak into the presentation layer, the same mapping gets duplicated in every ViewModel that uses that data, and swapping the data source forces changes in unrelated UI code. Keeping mapping at the boundary is what lets the API contract change without touching presentation.

  31. Should ViewModels own navigation, and what is the tension there?

    The common guidance is that ViewModels should not hold navigation controllers or Android navigation types, because navigation is a UI concern and coupling it to the ViewModel hurts testability and reuse. Instead the ViewModel signals intent, for example emitting a state or event that says navigate to details with a given id, and the composable or fragment, which owns the NavController, decides how to perform it. The tension is that this requires an event mechanism, so teams debate modeling navigation as a one-off event versus a consumable state field, but the ownership of the actual navigation call stays in the UI.

  32. How should errors propagate across data, domain, and presentation layers?

    Errors should be transformed as they cross boundaries rather than leaking low-level types upward: the data layer catches IOException or HTTP errors and maps them to domain-meaningful results, often a sealed Result type or a domain exception, and the presentation layer maps those into user-facing UI state like a message and a retry action. If a raw HttpException reaches the ViewModel, the presentation layer is now coupled to your networking library and must understand status codes, which is a layering violation. Modeling failures as return values rather than thrown exceptions across layers usually makes this cleaner and forces callers to handle them.

  33. What is the api/impl module split and why does it speed up builds?

    In this pattern a feature is split into an api module containing only interfaces and public models, and an impl module containing the concrete implementation, and other modules depend only on the api. Because the api's public surface rarely changes while the impl churns internally, changing the implementation does not invalidate the compilation of modules that only see the api, so Gradle can avoid recompiling and re-running annotation processing for dependents. This shrinks the incremental build graph and improves parallelism, which is the main reason large apps adopt it despite the extra module count.

  34. How does modularization enforce architectural boundaries that packages alone cannot?

    Within a single module, package-private and internal visibility are weak, and nothing stops one package from importing another's internals, so architectural rules rely on discipline and reviews. Splitting into modules makes a boundary compile-enforced: a module can only see the public API of modules it explicitly depends on, and you can prevent a feature from depending on another feature at all by simply not declaring the dependency. This turns please do not reach into that layer from a convention into a build error, which is the durable way to keep boundaries intact as a team grows.

  35. What distinguishes a core module from a feature module, and what dependency direction is allowed?

    Core modules provide shared, cross-cutting capabilities like networking, database, design system, or common utilities, and are meant to be depended upon by many features. Feature modules are self-contained vertical slices of user-facing functionality. The allowed direction is that features depend on core, and features generally do not depend on each other directly; when one feature must reach another, it goes through an api abstraction or a navigation contract in a shared module. A core module depending on a feature is a red flag that responsibilities are inverted.

  36. Why should feature modules avoid depending directly on each other, and what is the alternative?

    Direct feature-to-feature dependencies create a tangled graph that hurts build parallelism, causes circular-dependency risk, and couples features so they can no longer be developed or removed independently. The alternative is to depend on a shared api or contract module that declares the interface, for example a navigation entry or a data provider, with the concrete feature wired together only at the app or dependency-injection level. This keeps features decoupled at compile time while still letting them interact at runtime through inverted dependencies.

  37. What is the YAGNI-versus-abstraction judgment for adding a repository or use case in a tiny app?

    Abstractions pay off when they absorb change or enable testing, so a repository interface is worth it as soon as you need to fake a data source in tests or foresee multiple sources, but a repository that wraps a single Room DAO with no logic in a throwaway app is pure overhead. The judgment is to add the abstraction at the moment there is a concrete second reason for it, a test seam, a second implementation, or shared logic, not speculatively. Premature layering costs indirection and slows everyone down for a flexibility that may never be exercised.

  38. Why is it a problem to expose LiveData or StateFlow of a mutable collection, and how do you fix it?

    If the emitted value is a mutable list and something holds a reference and mutates it in place, observers will not be notified because the reference did not change, and StateFlow's equality-based deduplication can suppress emissions or, worse, the UI silently sees changed contents without a recomposition. The fix is to always emit immutable snapshots, replacing the whole value with a new immutable list on each change, so identity changes and equality comparison works. This is why UDF state objects should be immutable data classes copied via copy() rather than mutated.

  39. Why does StateFlow drop intermediate values and when does that bite you?

    StateFlow is conflated: it only keeps the latest value and a slow collector may miss intermediate states, and it also suppresses emissions when a new value equals the current one by equals(). This is fine for representing current UI state where only the latest matters, but it bites when you mistakenly use StateFlow for events, because equal consecutive events or rapid ones get dropped. It also means setting the same value twice produces no emission, so a pattern that relies on re-emitting an identical value to re-trigger something will silently do nothing.

  40. How should long-running work started in response to a user action be scoped so it is not tied to the screen lifecycle?

    Work that must complete regardless of whether the user leaves the screen, such as uploading a post, should not run in viewModelScope because that scope is cancelled when the ViewModel is cleared. It should be started in the data or domain layer within a longer-lived scope, an application-scoped coroutine scope injected into the repository, or handed to WorkManager for guaranteed execution across process death. Keeping it in the ViewModel means navigating away cancels the upload, which is a subtle and common correctness bug for fire-and-forget operations.

  41. What is the risk of a shared ViewModel scoped to a navigation graph or activity, and how do you reason about its lifetime?

    Scoping a ViewModel to an activity or a navigation graph lets multiple destinations share state, but its lifetime now extends across all those destinations, so stale state from a previous flow can leak into a new one and memory is held longer than a single screen needs. You must deliberately reset or clear state when a flow restarts, and be aware the ViewModel is cleared only when the whole scope, the nav graph back stack entry or activity, is gone. Over-broadening a ViewModel's scope to avoid passing arguments is a frequent source of surprising cross-screen state bugs.

  42. Why is init-block data loading in a ViewModel sometimes problematic, and what are alternatives?

    Loading data in the ViewModel init block runs eagerly the moment the ViewModel is created and cannot be controlled or retried cleanly, it can start work the UI is not ready to observe, and it makes tests trigger IO on construction. Alternatives include exposing a cold flow converted with stateIn using WhileSubscribed so loading starts when the UI actually subscribes, or triggering load from an explicit onStart event. The subscription-driven approach is cleaner because it naturally starts when observed and stops when not, aligning work with actual UI need.

  43. How do you keep business logic out of the ViewModel while still keeping it testable, and where does it go?

    Business rules, decisions like eligibility, pricing, or validation, belong in the domain layer as use cases or plain domain services, which are ordinary Kotlin classes with no Android dependencies and are the easiest thing in the codebase to unit test. The ViewModel then orchestrates: it calls the use case, maps the result into UI state, and manages presentation concerns. If those rules live inside the ViewModel, they get entangled with StateFlow and lifecycle, are harder to reuse across screens, and drag Android testing infrastructure into what should be pure logic tests.

  44. What is the subtle difference between passing an event up as a callback versus exposing it as a flow, in terms of who decides?

    When the UI calls a ViewModel function directly, onClick invoking viewModel.submit(), the decision and side effect are synchronous and the UI simply reports that something happened. When the ViewModel exposes an event flow that the UI collects, the ViewModel is telling the UI to do something like navigate. Conflating these leads to bidirectional confusion; the clean model is user actions go up as plain function calls, and UI-directive effects the ViewModel decides come down through state or a carefully-designed event channel, keeping the flow of control unambiguous.

  45. How can an offline-first architecture surface sync failures without breaking the source-of-truth model?

    Because the UI reads from the database, a sync failure must not be modeled by throwing to the UI; instead the sync status is itself data, stored or exposed alongside the content so the UI can show a subtle offline or sync-failed indicator while still rendering the last-known-good cached data. The repository or a sync manager updates that status, and the local database remains the single source of truth for content. This separates what to show, always the cache, from whether it is fresh, a status signal, which is the discipline that keeps offline-first coherent under failures.

  46. When a repository must expose both a reactive stream and imperative refresh, how do you avoid double sources of truth?

    The correct shape is a single observable stream from the database as the read path, plus a separate suspend refresh function whose only job is to fetch from network and write into that same database, never returning data to the caller. The UI observes the stream and calls refresh to trigger an update, so there is exactly one place the data lives. The antipattern is having refresh return the fetched list which the ViewModel then also stores, creating two representations that can disagree; the write-through design keeps the database authoritative.

  47. In a strict Clean Architecture setup, why might the domain layer define the repository interface while the data layer implements it, and what does that buy?

    Placing the repository interface in the domain layer means the innermost, dependency-free layer declares what it needs, and the outer data layer conforms to that contract, which is dependency inversion applied to layering: the arrow points inward. This buys you a domain that compiles and is fully testable with no knowledge of Room, Retrofit, or any framework, and it lets you replace the entire data layer without touching domain or presentation. If the interface lived in the data layer, the domain would depend outward on data, inverting the rule and coupling policy to detail.

  48. How do you decide whether a piece of derived UI data should be computed in the ViewModel, in a use case, or in the composable?

    If the derivation is pure presentation formatting used by one screen, a date string or a label, compute it near the UI or in the ViewModel's state mapping; if it encodes a business rule such as whether an order is refundable, it belongs in a use case so it is testable and reusable; and trivial layout-only derivations can live in the composable with remember or derivedStateOf. The trap is putting business decisions in the composable, where they cannot be unit tested and get duplicated, or doing heavy per-frame computation in the composable body instead of caching it. Match the computation's nature to the layer that owns that kind of concern.

  49. What are the architectural consequences of choosing exceptions versus a sealed Result type for cross-layer error handling?

    Exceptions propagate implicitly and can silently cross layer boundaries carrying framework-specific types, so a networking exception can surface in the UI without any layer being forced to handle or translate it, which erodes boundaries. A sealed Result type, Success or Error with a domain error, makes failure part of the function signature, forcing each layer to explicitly map and handle it, which keeps translation at boundaries and makes the happy and unhappy paths visible and testable. The tradeoff is more verbose call sites, so many teams use Result across public layer boundaries while still using exceptions for truly exceptional, unrecoverable conditions.

  50. You have a ViewModel that combines several flows into UiState with combine and stateIn, but the very first frame shows the initial value instead of a loading state and then flickers to content; what is happening and how do you fix it?

    combine does not emit until every source flow has emitted at least once, so before the database and other sources produce their first values the combined flow has nothing to emit, and stateIn therefore serves its initial value, which you may have set to something that renders as content or a wrong state. The fix is to design the initial value as an explicit Loading state, ensure each combined source has a defined initial emission so the combined result becomes meaningful quickly, and let the mapping compute Loading until real data arrives rather than assuming absence means empty. Reasoning about combine's wait-for-all semantics and stateIn's initial value together is what prevents the flicker.

Practice all Android Architecture questions interactively

Search, filter, and mark questions complete in the free Preparation Path. You can start immediately without an account.

Open free Preparation Path

More Android interview topics