关于InheritedWidget、updateShouldNotify、didChangeDependencies

本文解析了Flutter中元件重构与重渲的概念及其差异,并详细介绍了InheritedWidget和State类中updateShouldNotify与didChangeDependencies方法的工作原理。
X:
return A(
        data: someDataObject,
        child: B
    )

首先,我们应该清楚,无论何种情况,元件重构,该元件子树递归式全部重构。注意,重构与重渲是两个概念。重构消耗小,重渲消耗大。重构不一定重渲,而是对比之前的虚拟树构造,只构造渲染树的差异部分,最小化资源消耗。

通知条件:updateShouldNotify 执行:didChangeDependencies

updateShouldNotify方法在InheritedWidget类中。直译为“更新是否通知”;
didChangeDependencies方法在State类中,直译为“依赖更新时”;
它们的机制解析如下:

  • 如果有InheritedWidget元件 A,A下级有B(为状态元件)。A上级有X(也是有状态元件)。
  • 此时我们认定,B的dependence是A;
  • 当元件X发生setState,导致A元件重构。A元件实例被换,此时就发生了A的update;
  • A将通知B;
  • B将触发didChangeDependencies()
  • B可以在didChangeDependencies()中引用A的数据,来更新自己的状态。
  • A中重写updateShouldNotify()来过滤通知条件,就是什么条件下通知B;
Flutter 中,`InheritedWidget` 是一种用于在 widget 树中高效地向下传递数据的机制。它允许子 widget 直接访问祖先 widget 中的数据,而无需通过构造函数层层传递。这种方式非常适合用于状态管理,尤其是在需要在多个层级之间共享状态的情况下。 ### 基本用法 要使用 `InheritedWidget`,首先需要创建一个继承自 `InheritedWidget` 的类,并重写 `updateShouldNotify` 方法以决定是否需要通知子 widget 更新。以下是一个简单的示例: ```dart class CounterProvider extends InheritedWidget { final int count; final VoidCallback increaseCount; CounterProvider({ Key? key, required this.count, required this.increaseCount, required Widget child, }) : super(key: key, child: child); static CounterProvider? of(BuildContext context) { return context.dependOnInheritedWidgetOfExactType<CounterProvider>(); } @override bool updateShouldNotify(CounterProvider oldWidget) { return count != oldWidget.count; } } ``` 在这个例子中,`CounterProvider` 是一个 `InheritedWidget`,它包含了一个计数器值 `count` 和一个增加计数的方法 `increaseCount`。通过 `of` 方法,子 widget 可以轻松地访问这个 `InheritedWidget`。 ### 在 Widget 树中使用 接下来,可以在 widget 树中使用这个 `InheritedWidget`。通常,会在应用的根部或某个特定的子树中引入它: ```dart void main() { runApp( CounterProvider( count: 0, increaseCount: () {}, child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } ``` ### 访问和更新状态 子 widget 可以通过 `CounterProvider.of(context)` 来访问 `InheritedWidget` 中的状态,并调用其方法来更新状态: ```dart class MyHomePage extends StatelessWidget { final String title; const MyHomePage({Key? key, required this.title}) : super(key: key); @override Widget build(BuildContext context) { final counterProvider = CounterProvider.of(context)!; return Scaffold( appBar: AppBar( title: Text(title), ), body: Center( child: Text('Count: ${counterProvider.count}'), ), floatingActionButton: FloatingActionButton( onPressed: counterProvider.increaseCount, child: Icon(Icons.add), ), ); } } ``` ### 性能优化 虽然 `InheritedWidget` 提供了一种高效的机制来传递数据,但在处理大量数据或频繁更新时仍需注意性能。为了优化性能,可以在 `updateShouldNotify` 方法中返回 `false`,以避免不必要的重建。此外,如果需要更复杂的状态管理,可以考虑使用 `Provider` 或 `Riverpod` 等高级状态管理库,它们基于 `InheritedWidget` 提供了更多的功能和便利性[^3]。 ### 示例:使用 MultiProvider 如果你需要管理多个状态,可以使用 `MultiProvider` 将多个 `Provider` 组合在一起: ```dart void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => Counter()), ChangeNotifierProvider(create: (_) => AnotherModel()), ], child: MyApp(), ), ); } ``` 这种方式可以让你在不同的 widget 中访问不同的状态,而不需要将所有状态都放在一个 `InheritedWidget` 中[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值