テンプレートのカウンターアプリの実装
import 'package:flutter/material.dart';
// こちらが MyHomePage
// StatefulWidget
class MyHomePage extends StatefulWidget {
// title を受け取ってる
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
// Scaffold は土台みたいな感じ
return Scaffold(
// AppBar は上のヘッダー
appBar: AppBar(
title: Text(widget.title),
),
// Center で真ん中寄せ
body: Center(
// Column は [] の中身を縦に並べてくれる widget
// Row で横になる
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
// 右下のプラスボタン(Floating Action Button と言います)
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
簡単なカウンターアプリをRiverPodを使って実装してみた
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 👆 Riverpodを使うために追加が必要!
// StateProvider = 値を保持して、変更を通知してくれるProvider
final counterProvider = StateProvider<int>((ref) {
return 0; // 初期値
});
// 🏁 main関数もRiverpod用に変更
void main() {
runApp(
// ProviderScope で全体を囲む(必須!)
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Riverpod Counter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePageRiverpod(title: 'Riverpod Counter Demo'),
);
}
}
// 🔄 StatefulWidget → ConsumerWidget に変更
class MyHomePageRiverpod extends ConsumerWidget {
const MyHomePageRiverpod({super.key, required this.title});
final String title;
@override
Widget build(BuildContext context, WidgetRef ref) {
// 📖 ref.watch() でProviderの値を「監視」
// 値が変わったら自動で再描画される!
final counter = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$counter', // ←ここでcounterを表示
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 🔄 setState() → ref.read() に変更
// ref.read() は「一度だけ」値を取得・操作
ref.read(counterProvider.notifier).state++;
// または、より明示的に書くなら:
// ref.read(counterProvider.notifier).update((state) => state + 1);
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
final counterProvider = StateProvider<int>((ref) {
return 0; // 初期値
});
StateProvider<int>: 「変更可能な整数の値を管理する箱」って考えてください(後でproviderの種類を説明する)(ref){ return 0; }: 最初の値は0ですよ、という意味finalで定義してるので、このProvider自体は不変ですProviderScope(
child: MyApp(),
),
どこからでもProviderにアクセスできるようになります。
// 値の監視(値が変わると自動でリビルド)
final counter = ref.watch(counterProvider);
// 値の読み取りのみ(リビルドしない)
ref.read(counterProvider.notifier).state++
[watch]は「この値を監視して、変わったら画面を更新して!」[read]は「この値を一回だけ読み取って」
ボタンを押した時は一回だけ値を変更したいのでreadを使います。画面表示は常に最新の値を見せたいのでwatchを使うんです。