テンプレートのカウンターアプリの実装

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),
      ),
    );
  }
}

1. Providerの定義

final counterProvider = StateProvider<int>((ref) {
  return 0; // 初期値
});

2. ProviderScope

ProviderScope(
      child: MyApp(),
    ),

どこからでもProviderにアクセスできるようになります。

4. ref.watch と ref.read

// 値の監視(値が変わると自動でリビルド)
final counter = ref.watch(counterProvider);

// 値の読み取りのみ(リビルドしない)
ref.read(counterProvider.notifier).state++

[watch]は「この値を監視して、変わったら画面を更新して!」[read]は「この値を一回だけ読み取って」 ボタンを押した時は一回だけ値を変更したいのでreadを使います。画面表示は常に最新の値を見せたいのでwatchを使うんです。