Menu
CoddyTech

Provider:Consumer

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

ここでは、プロバイダーはMyApp自身のbuild内で作成され、同じbuildがそのすぐ下でランプを要求しています。アプリにはエラーが表示されます。contextはプロバイダーの上にあるMyAppに属しており、ウィジェットは自分より上にあるプロバイダーしか見つけられません。

Consumerを使えば解決できます。これはウィジェットなのでプロバイダーの下に配置され、そのbuilderには新しいcontextとモデル自体が渡されます。

Consumer<Lamp>(
  builder: (context, lamp, child) {
    return Text(lamp.isOn ? 'On' : 'Off');
  },
)

ランプがnotifyListeners()を呼び出すたびに、ランプを監視しているウィジェットのように、builderが再実行されます。その中では、モデルのメソッドをlampに対して直接呼び出せます。onPressed: () => lamp.toggle()のようにします。

Consumerはラップした部分だけを再ビルドするため、変化する部分をラップすれば、画面の残りの部分はそのまま保たれます。ほとんどのアプリでは、専用のウィジェット内でcontext.watchを使い、プロバイダーと同じbuild内にいる場合はConsumerを使います。

challenge icon

チャレンジ

中級

アプリを開くとエラーが表示されます。ランプの各部分をConsumerの中に配置してください。

  • ColumnをConsumer<Lamp>で囲み、そのビルダーからColumnを返してください。
  • その中では、アイコン、テキスト、ボタンにビルダーのlampを使用してください。

自分で試してみよう

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

class Lamp extends ChangeNotifier {
  bool _isOn = false;

  bool get isOn => _isOn;

  void toggle() {
    _isOn = !_isOn;
    notifyListeners();
  }
}

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Lamp(),
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(title: const Text('Lamp')),
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  context.watch<Lamp>().isOn ? Icons.lightbulb : Icons.lightbulb_outline,
                  size: 96,
                  color: context.watch<Lamp>().isOn ? Colors.amber : Colors.grey,
                ),
                Text(context.watch<Lamp>().isOn ? 'The lamp is on' : 'The lamp is off'),
                const SizedBox(height: 16),
                ElevatedButton(
                  onPressed: () => context.read<Lamp>().toggle(),
                  child: const Text('Switch'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
quiz icon腕試し

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

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

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