Menu
CoddyTech

Provider:WatchとRead

CoddyのFlutterジャーニー「状態管理」セクションの一部。レッスン 11/27。

Providerからモデルを取得する方法は2つあり、それぞれ異なる役割を果たします。

context.watch<StepCounter>()はモデルを取得し、同時に購読します。モデルがnotifyListeners()を呼び出すと、このウィジェットは再度ビルドされます。画面に表示するものには、build内で使います。

context.read<StepCounter>()は、購読せずにモデルを一度だけ取得します。メソッドを呼び出したいだけで、何も表示する必要がない場合は、onPressedなどのコールバック内で使います。

Widget build(BuildContext context) {
  final steps = context.watch<StepCounter>().steps;   // 表示する
  return ElevatedButton(
    onPressed: () => context.read<StepCounter>().walk(),   // 動作する
    child: Text('$steps steps'),
  );
}

使い分けを間違えると、その違いがわかります。build内でreadを使うと、最初の値がずっと表示されます。onPressed内でwatchを使うとエラーになります。タップはビルドではなく、購読するものがないためです。

challenge icon

チャレンジ

簡単

Walkはモデルに1000歩を加算しますが、画面は0 stepsのままです。

  • 歩数の行がモデルに追従するようにして、タップするたびに新しい数値が表示されるようにします。
  • ボタンの呼び出しはそのままにします。

自分で試してみよう

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

class StepCounter extends ChangeNotifier {
  int _steps = 0;

  int get steps => _steps;

  void walk() {
    _steps += 1000;
    notifyListeners();
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => StepCounter(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final steps = context.read<StepCounter>().steps;
    return Scaffold(
      appBar: AppBar(title: const Text('Steps')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('$steps steps', style: const TextStyle(fontSize: 40)),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                context.read<StepCounter>().walk();
              },
              child: const Text('Walk'),
            ),
          ],
        ),
      ),
    );
  }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

状態管理のすべてのレッスン

自分で練習してみよう: Flutterオンラインコンパイラ