Menu
CoddyTech

Riverpod:ProviderScope

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

Riverpod 是另一个用于共享状态的包,由和 Provider 同一个人编写,并吸取了一些经验教训。它最大的变化是:provider 不是树中的小部件,而是文件顶部、所有类之外的一个 final 变量:

import 'package:flutter_riverpod/flutter_riverpod.dart';

final quoteProvider = Provider((ref) => 'Small steps, every day.');

函数会为 provider 提供它的值。Riverpod 会在小部件首次请求时调用它,并保存结果。

这些值需要存放在某个地方,这就是 ProviderScope 的作用。它只需在 main 中放置一次,包住整个应用:

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

小部件通过 ref 读取 provider。ConsumerWidget 是一个 StatelessWidget,它的 build 会收到一个 ref:ref.watch(quoteProvider)。如果它上方没有 ProviderScope,这行代码就无处查找,应用会因找不到 No ProviderScope found 而停止。

challenge icon

挑战

简单

应用因找不到 No ProviderScope found 而停止。

  • 在 main 中用 ProviderScope 包裹 MyApp。
  • 将引言改为 Small steps, every day.。

亲手试试

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

final appNameProvider = Provider((ref) => 'Daily Quote');
final quoteProvider = Provider((ref) => 'Write your quote here.');

void main() {
  runApp(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 ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final appName = ref.watch(appNameProvider);
    final quote = ref.watch(quoteProvider);
    return Scaffold(
      appBar: AppBar(title: Text(appName)),
      body: Center(
        child: Text(quote, style: const TextStyle(fontSize: 24)),
      ),
    );
  }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

状态管理中的所有课

自己练习: Flutter 在线编译器