设计模式或方法
- InheritedWidget
- 原理:
InheritedWidget
是 Flutter 中用于在 widget 树中向下传递数据的一种机制。外层StatefulWidget
可以将需要共享的状态封装在一个继承自InheritedWidget
的类中。内层StatefulWidget
通过BuildContext.dependOnInheritedWidgetOfExactType
方法获取该共享状态。当外层StatefulWidget
的状态变化时,会通知依赖该InheritedWidget
的所有子 widget,只有依赖该状态的内层StatefulWidget
会重建。
- 示例代码:
class MyInheritedWidget extends InheritedWidget {
final int someValue;
MyInheritedWidget({required this.someValue, required Widget child}) : super(child: child);
static MyInheritedWidget? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) => someValue != oldWidget.someValue;
}
class OuterWidget extends StatefulWidget {
@override
_OuterWidgetState createState() => _OuterWidgetState();
}
class _OuterWidgetState extends State<OuterWidget> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return MyInheritedWidget(
someValue: _counter,
child: Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
_counter++;
});
},
child: Text('Increment'),
),
InnerWidget()
],
),
);
}
}
class InnerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final value = MyInheritedWidget.of(context)!.someValue;
return Text('Value from outer: $value');
}
}
- Provider
- 原理:Provider 是一个状态管理库,它基于
InheritedWidget
进行了封装和扩展,使得状态管理更加简单和可维护。外层StatefulWidget
可以将状态提供给 Provider,内层StatefulWidget
通过Consumer
或context.watch
来监听状态变化。当状态变化时,只有依赖该状态的Consumer
或context.watch
包裹的 widget 会重建。
- 示例代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CounterModel extends ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void increment() {
_counter++;
notifyListeners();
}
}
class OuterWidget extends StatefulWidget {
@override
_OuterWidgetState createState() => _OuterWidgetState();
}
class _OuterWidgetState extends State<OuterWidget> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => CounterModel(),
child: Column(
children: [
ElevatedButton(
onPressed: () {
context.read<CounterModel>().increment();
},
child: Text('Increment'),
),
InnerWidget()
],
),
);
}
}
class InnerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final value = context.watch<CounterModel>().counter;
return Text('Value from outer: $value');
}
}
性能优化
- 局部重建
- 使用
InheritedWidget
或Provider
时,确保只有依赖状态变化的内层StatefulWidget
进行重建。例如,在InheritedWidget
中,通过合理实现updateShouldNotify
方法,只有当共享状态实际发生变化时才通知子 widget 重建。在 Provider 中,Consumer
或context.watch
只关注特定的状态,减少不必要的重建范围。
- Memoization
- 对于内层
StatefulWidget
中一些计算开销较大的操作,可以使用 memoization 技术。例如,将计算结果缓存起来,当下次状态变化但计算参数未变时,直接使用缓存结果,避免重复计算。
- Widgets 的粒度控制
- 合理拆分 widget,将不需要根据外层状态变化而更新的部分独立出来,使其不参与因外层状态变化导致的重建。例如,如果内层
StatefulWidget
中有一部分 UI 始终不变,可以将其提取为一个独立的StatelessWidget
,减少重建带来的性能开销。