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

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.xdnf.cn/news/15739.html

相关文章:

  • 使用 docker 安装 openldap
  • 板凳-------Mysql cookbook学习 (十二--------1)
  • 从零开始的云计算生活——第三十三天,关山阻隔,ELK日志分析
  • 【Leetcode】栈和队列算法题(逆波兰表达式、二叉树层序遍历、最小栈、栈的压入弹出序列)
  • MySQL详解一
  • Oracle 成本优化器(CBO)与数据库统计信息:核心原理与实践
  • 【前端】Power BI自动化指南:从API接入到Web嵌入
  • docker安装与简单项目上手
  • 使用docker安装、启动jenkins服务(mac系统)
  • 3D工业相机是什么?如何选择和使用它?
  • 如何构建一个基于大模型的实时对话3D数字人?
  • 3D Gaussian Splatting (3DGS) 从入门到精通:安装、训练与常见问题全解析
  • c++:类型转换函数
  • 【神经网络在MATLAB中是如何实现的?】
  • 什么是 M4A 和 WAV?这两种音频互转会导致音质发生变化吗
  • kimi故事提示词 + deepseekR1 文生图提示
  • 不同相机CMOS噪点对荧光计算的影响
  • day23——Java网络编程终极指南:从基础到实战,全面掌握CS/BS架构通信
  • 【RL强化学习】Policy-Based Reinforcement Learning 策略学习
  • 知网学术不端论文检测查重助手(Windows)
  • [MRCTF2020]PYWebsite
  • Kubernetes (k8s)环境重启Pod方式总结
  • 访问网页的全过程笔记
  • SenseGlove力反馈手套:医疗、生产制造、军事模拟与远程机器人控制新革命
  • 游戏开发中防止“范围蔓延”
  • 部分排序算法的Java模拟实现(复习向,非0基础)
  • 多态,内部类(匿名内部类),常用API(1)
  • 推荐《Python 编程:从入门到实践》之Python编程的基础知识
  • H3CNE综合实验之机器人
  • Swift6.0 - 5、基本运算符