Riverpod in Flutter: solved counter exercise

  2 minutes

If you need a Riverpod Flutter solved example, this exercise gives you a clean baseline for shared state without relying on setState in the root widget.

Build an app with:

  • visible counter value,
  • increment button,
  • state handled through Riverpod.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateProvider<int>((ref) => 0);

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: CounterPage());
  }
}

class CounterPage extends ConsumerWidget {
  const CounterPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Riverpod Counter')),
      body: Center(child: Text('Value: $count', style: const TextStyle(fontSize: 24))),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: const Icon(Icons.add),
      ),
    );
  }
}

Each tap adds 1 and updates the UI immediately.

  • Forgetting ProviderScope at app root.
  • Using read to render UI instead of watch.
  • Mixing local and shared state without a clear boundary.

Riverpod is useful for apps that will grow in screens and shared logic.

It depends on project needs, but Riverpod often scales better and avoids context-related pitfalls.

StateProvider<int> is enough for this use case.

Yes. It is a solid starting point for larger state models.