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 を組み合わせることで、状態管理がより安全で扱いやすくなります!

