flutterでRiverpodとFreezedを使ってカウンターアプリを実装
2025 年 3 月 12 日 by marukorはじめに
flutterの標準カウンターアプリを、状態管理に Riverpod、データクラスに Freezed を使って実装します。
flutter開発に必須のライブラリなので使い方を習得していきましょう!
完成系はこんな感じです。

環境
os mac
version 3.27.1
必要なパッケージのインストール
dependencies: flutter: sdk: flutter flutter_riverpod: ^2.4.0 freezed_annotation: ^2.2.0 dev_dependencies: build_runner: ^2.4.6 freezed: ^2.3.5
Freezedを使った状態クラスの作成
import 'package:freezed_annotation/freezed_annotation.dart'; part 'counter_state.freezed.dart'; @freezed class CounterState with _$CounterState { const factory CounterState({@Default(0) int count}) = _CounterState; }
この CounterState は、count という整数を持つシンプルなデータクラスです。
StateNotifier を使ったカウンターの状態管理
CounterNotifier
を作成し、StateNotifierProvider
を使って状態を管理します。
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'counter_state.dart'; class CounterNotifier extends StateNotifier<CounterState> { CounterNotifier() : super(const CounterState()); void increment() { state = state.copyWith(count: state.count + 1); } } final counterProvider = StateNotifierProvider<CounterNotifier, CounterState>((ref) { return CounterNotifier(); });
UIの作成
カウンターを表示し、ボタンで増やす機能を実装します。
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'counter_notifier.dart'; void main() { runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Riverpod Freezed Counter', theme: ThemeData( primarySwatch: Colors.blue, ), home: const CounterPage(), ); } } class CounterPage extends ConsumerWidget { const CounterPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counterState = ref.watch(counterProvider); final counterNotifier = ref.read(counterProvider.notifier); return Scaffold( appBar: AppBar(title: const Text('Riverpod & Freezed Counter')), body: Center( child: Text( 'Count: ${counterState.count}', style: const TextStyle(fontSize: 24), ), ), floatingActionButton: FloatingActionButton( onPressed: counterNotifier.increment, child: const Icon(Icons.add), ), ); } }
コード全文
main.dart
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'main.freezed.dart'; // Freezedを使った状態クラス @freezed class CounterState with _$CounterState { const factory CounterState({@Default(0) int count}) = _CounterState; } // StateNotifier を使った状態管理 class CounterNotifier extends StateNotifier<CounterState> { CounterNotifier() : super(const CounterState()); void increment() { state = state.copyWith(count: state.count + 1); } } // Providerの定義 final counterProvider = StateNotifierProvider<CounterNotifier, CounterState>((ref) { return CounterNotifier(); }); void main() { runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Riverpod Freezed Counter', theme: ThemeData(primarySwatch: Colors.blue), home: const CounterPage(), ); } } class CounterPage extends ConsumerWidget { const CounterPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counterState = ref.watch(counterProvider); final counterNotifier = ref.read(counterProvider.notifier); return Scaffold( appBar: AppBar(title: const Text('Riverpod & Freezed Counter')), body: Center( child: Text('Count: ${counterState.count}', style: const TextStyle(fontSize: 24)), ), floatingActionButton: FloatingActionButton( onPressed: counterNotifier.increment, child: const Icon(Icons.add), ), ); } }
まとめ
- Freezed を使って状態クラス CounterState を定義。
- StateNotifier を使って状態管理を行う CounterNotifier を作成。
- ConsumerWidget を使用して UI で状態を監視。
このように、Riverpod と Freezed を組み合わせることで、状態管理がより安全で扱いやすくなります!