This repository contains a minimal and functional integration of Riverpod into Flutter’s default counter app.
It serves as an educational template for understanding how to set up and use Riverpod with code generation using build_runner.
To demonstrate how to refactor Flutter's default counter app to use Riverpod's latest approach, including annotations, code generation, and clean folder structure.
- Flutter 3.x
- Dart.
- Riverpod 2.6
- Riverpod Annotation.
- Riverpod Generator.
- build_runner.
- Install the riverpod dependencies in the pubspec.yaml (take into account the version at the time of installation).
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
flutter_riverpod: ^2.6.1 -> this
riverpod_annotation: ^2.6.1 -> this
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
build_runner: -> this
custom_lint: -> this
riverpod_generator: ^2.6.1 -> this
riverpod_lint: ^2.6.1 -> this
Important: After adding the dependencies and updating the pubspec.yaml, either with ctrl+s or flutter pub get, run the command dart run build_runner watch so that the providers code can be autogenerated (Example -> part 'count_provider.g.dart';).
- Wrap the MyApp() in ProviderScope() in main.dart.
void main() {
runApp(const ProviderScope(child: MyApp()));
}
- Create the providers folder and inside it create the provider that shares the state.
import 'package:riverpod_annotation/riverpod_annotation.dart';
//Mandatory for create the provider generated code.
part 'count_provider.g.dart';
//With this @riverpod decorator, it is inferred that a provider will be created.
@riverpod
class CountNotifier extends _$CountNotifier {
//initial value.
@override
int build() => 0;
//methods to update the state.
void increment() => state++;
}
- Create the shared folder and inside it create the widget that consumes the provider.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_test/providers/count_provider.dart';
//Change StatelessWidget for ConsumerWidget - Widget that consumes the provider.
class ButtonStateText extends ConsumerWidget {
const ButtonStateText({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(
countNotifierProvider); //returns the value of the provider's state variable.
return Text('$count');
}
}
- Change the StatefulWidget to ConsumerStatefulWidget and ConsumerState in the class that uses the shared widget (homepage.dart).
//Change StatefulWidget for ConsumerStateWidget.
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
ConsumerState<MyHomePage> createState() => _MyHomePageState();
}
- Change the method that increments the value of state to the increment method of the provider we have created.
floatingActionButton: FloatingActionButton(
onPressed: ref
.read(countNotifierProvider.notifier)
.increment, //read the (notifier) provider for use the methods for update state.
tooltip: 'Increment',
child: const Icon(Icons.add),
)
- Changes the basic text widget (Text) to the widget that receives the updated status value (ButtonStateText).
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
ButtonStateText() //Custom Widget
],
)
- ✅ Riverpod 2.6 with annotation-based syntax.
- ✅ Clean folder structure (providers, shared).
- ✅ Code generation via build_runner.
- ✅ Replacing StatefulWidget with ConsumerStatefulWidget.
- ✅ Readable and testable architecture.
- ✅ Minimal but complete working example.
🔗 Official documentation: https://riverpod.dev
Developed by Manuel Bacallado.
Flutter · Dart · Riverpod · State Management · Clean Architecture · Educational Project · Learning Project.