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

Flutter状态管理篇之ChangeNotifier(一)

目录

一、什么是ChangeNotifier?

二、ChangeNotifier的常用API

1.addListener

2.removeListener方法

3.notifyListeners

4.removerListener

三、ChangeNotifier的用法

1.定义状态类

2.创建StatefulWidget

3.完整代码

四、参考文档


        在 Flutter 中,状态管理是构建动态应用的核心。而在众多状态管理方式中,ChangeNotifier 是最基础、最常见的实现方式之一。

        本文将从原生角度 出发,不依赖任何第三方库(如 Provider),通过真实案例,带你理解 ChangeNotifier 的工作原理与使用方式。

一、什么是ChangeNotifier?

        ChangeNotifier 是一个 Flutter SDK 中的类,位于 foundation 包中。它提供了一种简单的观察者模式:

        可以注册监听器(addListener());

        当状态改变时调用 notifyListeners(),通知所有监听器更新状态。

它是 Flutter 原生支持的响应式状态模型,非常轻量,适合中小项目或局部状态管理。

二、ChangeNotifier的常用API

1.addListener

        ChangeNotifier 实现了“观察者模式”,允许其他对象“监听”它。当它的状态改变时(例如你调用了 notifyListeners()),它就会通知所有添加的监听器,让它们执行对应的逻辑,比如刷新 UI。

2.removeListener方法

        当页面销毁的时候,我们记得调用removeListener方法防止内存泄漏。

3.notifyListeners

        notifyListeners() 是 ChangeNotifier 类中的一个方法,用于通知所有通过 addListener() 注册的监听器:数据发生了变化。

        在下面的代码中:

class Counter extends ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;            // 状态发生变化notifyListeners();   // 通知监听器执行更新操作}
}

        它的工作原理如下: 

  1. 你调用 notifyListeners();

  2. 系统会遍历通过 addListener() 注册的所有监听器(回调函数);

  3. 执行每一个监听器的回调(例如 UI 中的 setState);

  4. 从而实现页面或逻辑的自动响应更新。

4.removerListener

        当你不再需要监听时,一定要调用 removeListener(),否则会内存泄漏。

三、ChangeNotifier的用法

        我们以下面的UI为例:

1.定义状态类

        首先我们定义一个继承自ChangeNotifier的类。

import 'package:flutter/foundation.dart';class Counter extends ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners(); // 通知监听器状态发生变化}
}

2.创建StatefulWidget

        我们将状态保存在 State 中,并手动监听它的变化。

class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {final Counter _counter = Counter(); // 创建状态对象@overridevoid initState() {super.initState();_counter.addListener(_onCounterChange);//添加监听器}void _onCounterChange(){setState(() {});}@overridevoid dispose() {super.dispose();_counter.removeListener(_onCounterChange);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text('当前用户点击次数',style: const TextStyle(fontSize: 12),),Container(height: 20,),Text('${_counter.count}',style: const TextStyle(fontSize: 20,fontWeight:FontWeight.bold ),)],),floatingActionButton: FloatingActionButton(onPressed: _counter.increment,tooltip: 'Increment',child: const Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.);}
}

3.完整代码

        完整的代码如下:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),),home: const MyHomePage(title: 'Flutter ChangeNotifier用法'),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {final Counter _counter = Counter(); // 创建状态对象@overridevoid initState() {super.initState();_counter.addListener(_onCounterChange);//添加监听器}void _onCounterChange(){setState(() {});}@overridevoid dispose() {super.dispose();_counter.removeListener(_onCounterChange);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text('当前用户点击次数',style: const TextStyle(fontSize: 12),),Container(height: 20,),Text('${_counter.count}',style: const TextStyle(fontSize: 20,fontWeight:FontWeight.bold ),)],),floatingActionButton: FloatingActionButton(onPressed: _counter.increment,tooltip: 'Increment',child: const Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.);}
}class Counter extends ChangeNotifier{int _count = 0;int get count => _count;void increment() {_count++;notifyListeners(); // 通知监听器状态发生变化}
}

        这里要注意的是我们忘记了在dispose函数中移除观察者,否则会有内存泄漏的风险。

四、参考文档

  • Flutter 官方文档:ChangeNotifier

  • Flutter 状态管理综述

http://www.lryc.cn/news/591296.html

相关文章:

  • 深度学习之神经网络(二)
  • Flutter基础(前端教程①②-序列帧动画)
  • Oracle数据泵详解——让数据迁移像“点外卖”一样简单​
  • 如何查询pg账号权限 能否创建模式 删表建表
  • xss防御策略
  • 从 0 到 1 玩转 XSS - haozi 靶场:环境搭建 + 全关卡漏洞解析
  • OpenCV中VideoCapture 设置和获取摄像头参数和Qt设计UI控制界面详解代码示例
  • 用Python实现神经网络(二)
  • 前端0知识docker临危之被迫弄docker教程
  • NumPy, SciPy 之间的区别
  • ota之.加密算法,mcu加密方式
  • 量化环节:Cont‘d
  • C++网络编程 6.I/0多路复用-epoll详解
  • 现在遇到一个问题 要使用jmeter进行压测 jmeter中存在jar包 我们还要使用linux进行发压,这个jar包怎么设计使用
  • cherry使用MCP协议Streamable HTTP实践
  • RSTP:快速收敛的生成树技术
  • 笔试——Day11
  • 退休时间计算器,精准预测养老时间
  • GraphQL的N+1问题如何被DataLoader巧妙化解?
  • leetcode 3202. 找出有效子序列的最大长度 II 中等
  • Spring整合MyBatis详解
  • kimi故事提示词 + deepseekR1 文生图提示
  • [yotroy.cool] 记一次 spring boot 项目宝塔面板部署踩坑
  • Qt5 与 Qt6 详细对比
  • modbus 校验
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | PasswordGenerator(密码生成器)
  • EPLAN 电气制图(十): 绘制继电器控制回路从符号到属性设置(上)
  • Everything(文件快速搜索)下载与保姆级安装教程
  • Spring IoCDI_2_使用篇
  • JAVA中的Map集合