カウンターアプリのコード

準備:flutter_riverpodの導入

ステップ1: pubspec.yamlにパッケージを追加

dependencies:
  flutter:
    sdk: flutter
  flutter_riverpod: ^  # 最新バージョンを確認してください

dev_dependencies:
  flutter_test:
    sdk: flutter

ステップ2: main.dartでProviderScopeを設定

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(
    // すべてのProviderを利用できるようにするためのラッパー
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Riverpod Tutorial',
      home: HomePage(),
    );
  }
}

なぜProviderScopeが必要?

Providerの種類と使い分け

Provider:読み取り専用の値を提供

特徴: 一度作成されたら変更されない値やオブジェクトを提供

// 例1: 設定値を提供
final apiUrlProvider = Provider<String>((ref) {
  return '<https://api.example.com>';
});

// 例2: リポジトリクラスのインスタンスを提供
final userRepositoryProvider = Provider<UserRepository>((ref) {
  final apiUrl = ref.watch(apiUrlProvider);
  return UserRepository(apiUrl: apiUrl);
});

// 例3: 計算結果を提供
final taxIncludedPriceProvider = Provider<double>((ref) {
  final basePrice = ref.watch(basePriceProvider);
  return basePrice * 1.1; // 10%の税金を含む
});

StateProvider:単純な状態の変更を管理

特徴: プリミティブ型(int、String、boolなど)の状態管理に最適

// 例1: カウンターの状態
final counterProvider = StateProvider<int>((ref) => 0);

// 例2: テーマの切り替え
final isDarkModeProvider = StateProvider<bool>((ref) => false);

// 例3: フォームの入力値
final nameInputProvider = StateProvider<String>((ref) => '');

// 使用例
class SettingsPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isDarkMode = ref.watch(isDarkModeProvider);
    
    return Scaffold(
      body: Column(
        children: [
          SwitchListTile(
            title: Text('ダークモード'),
            value: isDarkMode,
            onChanged: (value) {
              // 状態を更新
              ref.read(isDarkModeProvider.notifier).state = value;
            },
          ),
        ],
      ),
    );
  }
}

2.3 WidgetからProviderを読み取る3つの方法

ref.watch:状態の監視(UI表示用)

class CounterDisplay extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 状態が変わると自動的にWidgetが再ビルドされる
    final count = ref.watch(counterProvider);
    
    return Text('現在のカウント: $count');
  }
}