Sparround

Comparison and justifying the choice

In an interview, the "which state management?" question is not after a library name — it wants to see your decision process. The structure of a strong answer:

1. Ask for context (team, product lifetime, share of async work, audit requirements). 2. Name the criteria. 3. Make the decision and state why you rejected the alternative. 4. Name the risk and how you mitigate it. 5. Cite the official position: the Flutter team gives no single recommendation — the choice depends on the app's complexity, the team's preferences and the problems to be solved.

QuestionProviderRiverpod 3BLoC / Cubit
Learning curveLowMedium (a new mental model)Medium-high (event/state discipline)
Async stateHand-written flags`AsyncValue` built inA status enum or sealed states
Reading a wrong providerA runtime errorVisible at compile timeA runtime error
Testing: replacing a dependencyRebuilding the tree by hand`overrides` — one line`bloc_test`, `MockBloc`, `whenListen`
Testing the state sequenceA hand-written listener`container.listen``blocTest(expect: ...)` — the most ready-made
Audit / event logHand-rolledObservers`BlocObserver` plus `onTransition`
Debounce / concurrency controlHand-rolledHand-rolled (or indirectly via `select`/`autoDispose`)`EventTransformer` plus `bloc_concurrency`
The official DI recommendationChosen by the official case studyThe provider graph doubles as DI`RepositoryProvider` (provider inside)

A fact that stands out in an interview: flutter_bloc implements BlocProvider, MultiBlocProvider and RepositoryProvider with package:provider and re-exports its context.read/watch/select extensions. So "Provider or BLoC?" is not a question about mechanism — it is a question about discipline and convention. That answer lifts the comparison above the surface level.

Ready-made argument sets (usable verbatim in an interview):

  • Why Riverpod? — Async state comes built in (AsyncValue), dependencies are replaced in tests with a one-line override, providers are checked at compile time, and autoDispose cleans memory on its own. The cost: a new mental model and codegen build time.
  • Why BLoC? — The docs' two points: traceability (onTransition, state → event → state) and advanced event transformations (debounce, droppable). A discipline advantage in audited flows and large teams. The cost: boilerplate.
  • Why Provider? — The lowest learning curve, the DI choice of the official architecture case study, and the official example in Flutter's docs. Enough for small and medium apps. The cost: hand-written async state and runtime errors.
  • Why mixed? — BLoC for the payment flow (audit), Riverpod for the rest (async). The condition: the boundary is documented and never mixed within a screen.

📚 Sources and documentation