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 中:

  • 用 Consumer<Lamp> 包裹 Column,并在它的 builder 中返回 Column。
  • 在其中,使用 builder 的 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 在线编译器