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(); // 通知监听器执行更新操作}
}
它的工作原理如下:
-
你调用 notifyListeners();
-
系统会遍历通过 addListener() 注册的所有监听器(回调函数);
-
执行每一个监听器的回调(例如 UI 中的 setState);
-
从而实现页面或逻辑的自动响应更新。
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 状态管理综述