当前位置: 首页 > news >正文

Provider中的watch、read、Consumer、ChangeNotifierProvider、ValueNotifierProvider

一、watch、read、Consumer状态消费API

watch 和 Consumer 都用于监听状态变化并重建 Widget,但 watch 是通过 BuildContext 的扩展方法实现,更简洁,适用于简单场景;Consumer 是一个 Widget,提供了更灵活的构建方式,适用于需要精细控制 Widget 结构的场景。
read 与 watch 和 Consumer 的主要区别在于它不监听状态变化,用于获取状态对象执行非 UI 相关操作,避免不必要的 Widget 重建。在实际使用中,通常会结合 watch 或 Consumer 以及 read 来实现既高效又灵活的状态管理和 UI 更新。

1.1. watch

功能watch 用于监听状态变化。当被监听的状态对象发生改变时,使用 watch 的 Widget 会自动重建。它内部依赖 InheritedWidget 机制来检测状态变化。

使用场景:适用于需要根据状态变化更新 UI 的场景。例如,在一个计数器应用中,当计数器的值发生变化时,UI 需要显示最新的计数值。

代码示例

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}void main() {runApp(ChangeNotifierProvider(create: (context) => Counter(),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('Provider watch示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 使用watch获取并监听Counter状态Text('计数: ${context.watch<Counter>().count}'),ElevatedButton(onPressed: () {context.read<Counter>().increment();},child: Text('增加计数'),),],),),),);}
}

在上述代码中,context.watch<Counter>().count 用于获取 Counter 实例并监听其变化。当调用 increment 方法改变计数器的值时,Text 组件会因为状态变化而重建,从而显示最新的计数值。

1.2. read

功能read 用于读取状态对象,但不会监听状态变化。它主要用于在不希望 Widget 因状态变化而重建的情况下获取状态对象,例如执行一些与 UI 更新无关的操作,如业务逻辑处理、数据计算等。

使用场景:当你需要获取状态对象来执行一些非 UI 相关的操作时,read 是一个合适的选择。例如,在点击按钮增加计数器值的逻辑中,我们只需要获取 Counter 对象来调用 increment 方法,而不需要监听其变化来更新 UI(因为更新 UI 的操作由 watch 负责)。

代码示例:上述计数器示例中,context.read<Counter>().increment(); 就是使用 read 获取 Counter 对象并调用其 increment 方法,这里不需要监听 Counter 的变化,所以使用 read 而不是 watch

1.3. Consumer

功能Consumer 也是用于监听状态变化并重建 Widget。它通过 Builder 回调来构建依赖状态的 Widget。与 watch 不同的是,Consumer 是一个 Widget,它允许你更灵活地控制依赖状态的 Widget 在 Widget 树中的位置和结构。

使用场景:当你希望在 Widget 树的特定位置,基于状态构建一个 Widget 时,Consumer 非常有用。例如,你可能只想在页面的某个特定区域根据状态更新 UI,而不是整个 Widget 因为状态变化而重建。

代码示例

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}void main() {runApp(ChangeNotifierProvider(create: (context) => Counter(),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('Provider Consumer示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<Counter>(builder: (context, counter, child) {return Text('计数: ${counter.count}');},),ElevatedButton(onPressed: () {context.read<Counter>().increment();},child: Text('增加计数'),),],),),),);}
}

在上述代码中,Consumer<Counter> 包裹的 Text 组件会根据 Counter 状态的变化而重建,通过 builder 回调构建依赖 Counter 状态的 Widget。

二、ChangeNotifierProvider

用于管理实现了 ChangeNotifier 接口的状态对象。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}void main() {runApp(ChangeNotifierProvider(create: (context) => Counter(),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('ChangeNotifierProvider示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<Counter>(builder: (context, counter, child) {return Text('计数: ${counter.count}');},),ElevatedButton(onPressed: () {context.read<Counter>().increment();},child: Text('增加计数'),),],),),),);}
}

在这个例子中,Counter 类继承自 ChangeNotifierChangeNotifierProvider 提供了 Counter 实例,Consumer 监听 Counter 的变化,当调用 increment 方法并触发 notifyListeners() 时,Consumer 包裹的 Text 会更新。

三、ValueNotifierProvider

用于管理实现了 ValueNotifier 的状态对象。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';void main() {runApp(ValueNotifierProvider(create: (context) => ValueNotifier<int>(0),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('ValueNotifierProvider示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<ValueNotifier<int>>(builder: (context, valueNotifier, child) {return Text('值: ${valueNotifier.value}');},),ElevatedButton(onPressed: () {context.read<ValueNotifier<int>>().value++;},child: Text('增加值'),),],),),),);}
}

这里 ValueNotifierProvider 提供了一个 ValueNotifier<int> 实例,Consumer 监听其值的变化,通过修改 value 触发更新。


四:示例场景:监听 model 中特定属性并实现局部刷新


假设 model 中有三个属性 abc,只监听其中一个属性,比如 a。可以通过自定义 ChangeNotifier 类,并在更新 a 时只通知关心 a 的 Consumer

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';class MyModel with ChangeNotifier {int a = 0;int b = 0;int c = 0;void updateA(int newA) {a = newA;notifyListeners();}void updateB(int newB) {b = newB;// 不通知,因为我们不关心b的变化对某些Consumer的影响}void updateC(int newC) {c = newC;// 不通知,因为我们不关心c的变化对某些Consumer的影响}
}void main() {runApp(ChangeNotifierProvider(create: (context) => MyModel(),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('局部刷新示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<MyModel>(builder: (context, model, child) {return Text('属性a的值: ${model.a}');},),ElevatedButton(onPressed: () {context.read<MyModel>().updateA(context.read<MyModel>().a + 1);},child: Text('增加属性a的值'),),// 这里省略对b和c的操作示例,因为不关心它们对这个Consumer的影响],),),),);}
}

在上述代码中,MyModel 类继承自 ChangeNotifierupdateA 方法在更新 a 属性后调用 notifyListeners(),而 updateB 和 updateC 方法不调用。这样,只有监听 a 属性变化的 Consumer 会在 a 变化时进行局部刷新。如果要更细粒度地控制通知,可以使用 Listenable 或更复杂的状态管理模式来实现只通知特定的 Consumer。例如,使用 ValueNotifier 分别管理不同的属性,这样每个属性的变化只会通知依赖它的 Consumer

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';class MyModel {final ValueNotifier<int> a = ValueNotifier<int>(0);final ValueNotifier<int> b = ValueNotifier<int>(0);final ValueNotifier<int> c = ValueNotifier<int>(0);
}void main() {runApp(ChangeNotifierProvider(create: (context) => MyModel(),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('局部刷新示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<MyModel>(builder: (context, model, child) {return ValueListenableBuilder<int>(valueListenable: model.a,builder: (context, aValue, child) {return Text('属性a的值: $aValue');},);},),ElevatedButton(onPressed: () {context.read<MyModel>().a.value++;},child: Text('增加属性a的值'),),],),),),);}
}

这里使用 ValueNotifier 分别管理 abc 属性,ValueListenableBuilder 只监听特定的 ValueNotifier,从而实现更精确的局部刷新。

http://www.dtcms.com/a/365709.html

相关文章:

  • 信息融智学=信息哲学+信息科学+信息技术+信息系统工程+信息处理之智
  • 数据库选择有讲究?SQLite、PostgreSQL还是MySQL?
  • 全渠道 + 低代码:如何打造 “内外协同” 的客服管理系统体系?
  • http和https区别是什么
  • docker 安装 redis 并设置 volumes 并修改 修改密码(三)
  • 【TypeScript】事件循环
  • k8s的SidecarSet配置和initContainers
  • 《四川棒球知识百科》球速最快的运动之一·棒球1号位
  • Omi录屏专家 Screen Recorder Mac中文
  • 如何在私域运营中快速建立信任,三招解决你的烦恼!
  • linux---------------网络基础概念
  • 【IQA技术专题】 无参考自然图像IQA:NIQE
  • 审核问题——一个关于版本号的乌龙事件
  • Elasticsearch面试精讲 Day 6:Query DSL查询语法详解
  • 2025年9月,十大求职神器测评:谁是Offer收割机之王?
  • 玳瑁的嵌入式日记D32-0903(网络编程)
  • Nginx简介
  • 自学嵌入式第三十四天:网络编程-TCP
  • dumpsys alarm 简介
  • Java+AI开发实战与知识点归纳系列:Spring流式输出实战——LangChain4j与Ollama集成
  • Spring Authorization Server 1.5.2 使用YML配置的方式,最常用法总结
  • VAR的教师强制teacher forcing
  • Canaan 阿瓦隆 A1246I 81T矿机评测:性能、功耗与能效全面分析
  • 解锁产品说明书的“视觉密码”:多模态 RAG 与 GPT-4 的深度融合 (AI应用与技术系列)
  • 【收藏必备】大模型面试宝典:Transformer到实战应用全解析,助你斩获30W年薪offer!
  • Debezium日常分享系列之:Debezium 3.3.0.Alpha2发布
  • MySQL 行转列 (Pivot) 的 N 种实现方式:静态、动态与 GROUP_CONCAT 详解
  • C++入门小馆:C++11第一弹
  • 面试复习题-Flutter
  • https 协议与 wss 协议有什么不同