当前位置: 首页 > 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.dtcms.com/a/284321.html

相关文章:

  • 什么是协变(Covariant)与逆变(Contravariant)?
  • 在 Windows Server RDS 上配置用户配置文件磁盘查找对应的用户名
  • 第2章通用的高并发架构设计——2.5 高并发读场景总结:CQRS
  • 【计算机网络】第四章:网络层(上)
  • Spring中事务失效的情况深度分析
  • 深入理解 KVM 子系统:从虚拟化核心到内核实现的全景解析
  • 7.18 note
  • 第十八节:第三部分:java高级:反射-获取构造器对象并使用
  • 【参数初始化】——深度学习.全连接网络
  • Cadence SPB 2024软件下载及安装教程|Cadence软件安装详细步骤附下载链接
  • Spring IoCDI_2_使用篇
  • Anime.js 超级炫酷的网页动画库详解
  • 【图像质量评价指标】信噪比(Signal-to-Noise Ratio,SNR)
  • Linux 基础指令
  • makefile missing separator. Stop.问题
  • 一款实用的.NET Core加密解密工具类库
  • C++11之lambda表达式与包装器
  • 20.轮廓特征与近似,改变图像的轮廓识别画线的精确度,同时画出轮廓对应的矩形
  • GitHub 趋势日报 (2025年07月16日)
  • 【Burp入门第三十八篇】Repeater Strike:AI 驱动的 Burp Suite 插件
  • Effective Modern C++ 条款13:优先考虑const_iterator而非iterator
  • Magenta RT 正式开源!实时生成多种风格音乐,让创作无门槛
  • 【C++详解】STL-stack、queue的模拟实现,容器适配器,deque双端队列介绍
  • Java 大视界 -- Java 大数据在智能交通智能公交站台乘客流量预测与服务优化中的应用(349)
  • 19.删除链表的倒数第 N 个结点
  • 多线程--sem_wait(sem)特殊用法
  • 拿到安全工程师证后,能从事哪些岗位?
  • C函数实现strcopy strcat strcmp strstr
  • javax.servlet.http.HttpServletResponse;API导入报错解决方案
  • Kotlin集合与空值