Provider是什么,Flutter应用程序的状态管理器

作者: IT Sectr 发布日期: 2026-02-19 阅读时间: 7 分钟

Provider — Flutter的状态管理包,由Rémi Rousselet于2019年创建,作为InheritedWidget的封装。Provider解决了无需props drilling将数据传递到组件树下层的问题:任何组件都可以通过context.read<T>()context.watch<T>()访问状态。据pub.dev,Provider是Flutter最受欢迎的状态管理器,拥有超过2.5万个点赞。

主要内容

  • ChangeNotifier — 带有notifyListeners的类,用于通知订阅者变化
  • Consumer — 当ChangeNotifier变化时重新构建的组件
  • MultiProvider — 无需嵌套即可组合多个Provider
  • ProxyProvider — 依赖于另一个Provider的Provider
  • context.read / context.watch — 无订阅和带订阅的状态读取方法

什么是Provider?

Provider — 基于InheritedWidget构建的Flutter状态管理和依赖注入包。Provider在组件树中提供对象(状态、服务、仓库),并在数据变化时自动重建UI。与直接使用InheritedWidget不同,Provider消除了所有模板代码。

Provider是Google官方推荐的Flutter状态管理方式(Flutter Team, 2019-2023〉。据Flutter Community Survey 2025,72%的Flutter应用程序使用Provider。

ChangeNotifier和notifyListeners

ChangeNotifier — 实现Listener模式的Flutter内置类。ChangeNotifier通过调用notifyListeners()通知订阅者变化。

Dart
class CounterProvider extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }

  void reset() {
    _count = 0;
    notifyListeners();
  }
}

notifyListeners规则:在数据完全变更后调用—不是在方法中间,而是在结尾。如果方法执行多次变更,在所有变更后调用一次notifyListeners()

Consumer和context.watch

Consumer — 订阅ChangeNotifier并在每次notifyListeners()调用时重新构建的组件。

Dart
Consumer<CounterProvider>(
  builder: (context, provider, child) => Column(
    children: [
      child!, // 不重新构建
      Text('${provider.count}'),
      ElevatedButton(
        onPressed: () => provider.increment(),
        child: Icon(Icons.add),
      ),
    ],
  ),
  child: Text('计数器:'),
)

context.watch — 用于订阅Provider的BuildContext扩展方法。context.read — 无订阅访问。context.select — 订阅模型的特定字段。

MultiProvider和ProxyProvider

MultiProvider — 用于注册多个Provider而无需嵌套的组件。ProxyProvider — 依赖于另一个Provider的Provider。

Dart
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => CartProvider()),
    ChangeNotifierProvider(create: (_) => AuthProvider()),
    ProxyProvider<AuthProvider, OrderProvider>(
      update: (_, auth, __) => OrderProvider(auth.userId),
    ),
  ],
  child: MaterialApp(home: HomePage()),
)

测试Provider

Provider测试通过将组件包装在带有测试值的MultiProvider中进行。

Dart
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('Counter increments on button tap',
    (tester) async {
      await tester.pumpWidget(
        ChangeNotifierProvider(
          create: (_) => CounterProvider(),
          child: CounterScreen(),
        ),
      );
      await tester.tap(find.byKey(Key('increment')));
      await tester.pump();
      expect(find.text('1'), findsOneWidget);
    },
  );
}

Provider:性能和局限性

Provider性能基于InheritedWidget:当Provider变化时,所有通过context.watch或Consumer订阅的组件都会重建。使用context.select、带child参数的Consumer和静态组件的const

方法订阅重建用途
context.watch完整模型任何变化简单组件
Consumer完整模型任何变化带child优化
context.select特定字段仅在字段变化时复杂模型
context.read从不事件处理器

常见问题

Provider与BLoC有什么区别?

Provider — 使用ChangeNotifier进行依赖注入的InheritedWidget封装。BLoC — 使用Event+Stream进行逻辑分离的架构模式。

什么是ChangeNotifierProvider?

ChangeNotifierProvider — 用于ChangeNotifier实例的Provider类型。通过create创建对象,向后代提供,并在调用notifyListeners时重建Consumer。

如何避免与Provider的不必要重建?

使用context.select代替context.watch。将大的ChangeNotifier分裂成多个小的。

可以在没有ChangeNotifier的情况下使用Provider吗?

可以。Provider用于不可变对象。StreamProvider用于流。FutureProvider用于Future。ProxyProvider用于依赖其他Provider的Provider。

什么是ProviderNotFoundException?

ProviderNotFoundException — 弝图获取在组件树中未声明的Provider时发生的运行时异常。

总结

  • Provider — 用于Flutter状态管理和DI的InheritedWidget封装
  • ChangeNotifier — 带有notifyListeners的类,用于响应式UI更新
  • Consumer和context.watch — 自动重建的变化订阅
  • MultiProvider — 无需树嵌套的provider组合
  • ProxyProvider — Provider之间的依赖链
  • context.select — 模型特定字段的点订阅
  • StreamProvider和FutureProvider — 内置支持响应式和异步数据

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读