理解 create 指向的箭头函数
场景
void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return ChangeNotifierProvider(create: (context) => MyAppState(),child: MaterialApp(title: 'Namer App',theme: ThemeData(useMaterial3: true,colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),),home: MyHomePage(),),);}
}
Analysis
在 ChangeNotifierProvider
里,create:
参数接收一个函数,用来“现场”构造要提供给子树的对象。写成
create: (context) => MyAppState(),
可以逐句拆解成下面几点:
片段 | 含义 | iOS 类比 |
---|---|---|
(context) => ... | 匿名函数(或称“箭头函数”);框架在插入 Provider 时调用一次。context 是当前 Provider 所在节点的 BuildContext ,很少用到,但可用于读取别的 Provider 或 Theme。 | 类似在 loadView() 里用闭包初始化子视图 |
MyAppState() | 函数返回的新实例。因为 MyAppState 继承自 ChangeNotifier ,它具备 addListener / notifyListeners 等能力,能在数据变动时通知 UI 重建。 | 自己写的 Observable / NSNotification 发布者 |
返回值 | 这就是 Provider 要“注入”进 widget tree 的状态对象。子树里可以 context.watch<MyAppState>() 拿到同一个实例。 | 单例 / 依赖注入容器里保存的共享实例 |
生命周期 & 线程
-
只创建一次
- 当
ChangeNotifierProvider
首次出现在 widget tree 时,框架调用create
。 - 后续因父组件
setState
导致的重建不会再执行create
——实例被缓存并复用。
- 当
-
自动释放
- 当 Provider 被移出 widget tree(比如页面 pop),它会自动调用
dispose()
,而ChangeNotifierProvider
已经帮你把MyAppState.dispose()
调好。 - 你无需手动管理内存/订阅取消,和 SwiftUI 的
@StateObject
有点像。
- 当 Provider 被移出 widget tree(比如页面 pop),它会自动调用
-
主线程保证
- Flutter 所有 UI 更新与通知回调默认都在主 isolate(≈ 主线程)执行,不用担心线程切换。
为什么不用 value:
?
ChangeNotifierProvider(value: someExistingInstance,child: ...
)
value:
只适合已经存在的对象(比如从外部传进来的单例)。- 如果自己 new 一个对象再塞给
value:
,Provider 就不知道何时该自动dispose()
,容易造成内存泄漏。 - 因此自己创建对象时,应优先用
create:
。
总结
create:
负责 实例化 并 托管 状态对象;- Provider 把该对象挂在 widget tree 上,供后代通过
context.watch / read / select
访问; - 当 Provider 被移除时,自动
dispose()
,让资源安全回收。
把这点想成“Provider = 带生命周期管理的依赖注入容器”,就不难理解了。