I am starting a medium sized Flutter app (auth, lists from an API, a cart). Tutorials show Provider, Riverpod, Bloc and GetX. I do not want to rewrite the state layer in six months. What should I choose and why?
#flutter#provider#riverpod#state
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
I am starting a medium sized Flutter app (auth, lists from an API, a cart). Tutorials show Provider, Riverpod, Bloc and GetX. I do not want to rewrite the state layer in six months. What should I choose and why?
#flutter#provider#riverpod#state
Short answer
For most new apps, pick Riverpod. For a small app or a team already fluent in it, Provider with ChangeNotifier is fine. Pick Bloc if your team wants strict event/state separation and lots of enforced structure.
How they differ
| Provider | Riverpod | Bloc | |
|---|---|---|---|
| Needs BuildContext to read | yes | no (providers are global, scoped by ProviderScope) | yes (BlocProvider) |
| Async data | manual | AsyncValue built in | states you model yourself |
| Compile-time safety | runtime ProviderNotFoundException possible | much stronger | good |
| Boilerplate | low | low to medium | high |
| Testing | OK | very easy (override providers) | very easy |
Why Riverpod is a good default
AsyncValue), so you stop writing three booleans per screen.final productsProvider = FutureProvider<List<Product>>((ref) async {
final api = ref.watch(apiProvider);
return api.fetchProducts();
});
class ProductsPage extends ConsumerWidget {
const ProductsPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final products = ref.watch(productsProvider);
return products.when(
data: (list) => ProductList(list),
loading: () => const CircularProgressIndicator(),
error: (e, st) => Text('Failed: $e'),
);
}
}
Avoid rewrites
Keep business logic in plain Dart classes (repositories and services) that know nothing about Flutter, and let the state library only expose them to the UI. Then switching libraries later means changing a thin layer, not the logic.
Recommendation on GetX
It mixes routing, DI and state in one global style that is hard to test and to migrate away from; we would not start a long-lived project on it.