Menu
CoddyTech

Provider:监听还是读取

本课属于 Coddy Flutter 学习旅程的“状态管理”单元。第 11 课,共 27 课。

从 Provider 获取模型有两种方式,它们的作用不同。

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 在线编译器