一、问题
flutter 因为渲染机制,层级越深渲染代价越大。怎么解决这个问题呢?大体分为以下种:
1、将局部组件缓存;
2、将方法组件抽出成继承 StatefulWidget 和 StatelessWidget 的子组件,利用系统优化机制;
3、使用 RepaintBoundray 包裹频繁变化的组件,变化限制在低层级;
4、使用 Provider 等第三方库;
...
今天讨论第 2 条:虽然我一直知道这样可以优化,但是在不那么计较性能的页面我都是采用的函数组件,原因有三条:
1)、文件数量额外多出一些;
2)、拆分麻烦(其实是懒);
3)、不够优雅;
那么有没有一种实现可以完美满足以上三种最佳实现呢???
当然有!!!
二、解决方案
今天无意间研究 flutter 源码时发现了寻找了很久的最佳实践:
Builder & StatefulBuilder
1、Builder 源码:
typedef WidgetBuilder = Widget Function(BuildContext context);
class Builder extends StatelessWidget {
const Builder({
Key? key,
required this.builder,
}) : assert(builder != null),
super(key: key);
final WidgetBuilder builder;
@override
Widget build(BuildContext context) => builder(context);
}
2、StatefulBuilder 源码:
typedef StatefulWidgetBuilder = Widget Function(BuildContext context, StateSetter setState);
class StatefulBuilder extends StatefulWidget {
const StatefulBuilder({
Key? key,
required this.builder,
}) : assert(builder != null),
super(key: key);
final StatefulWidgetBuilder builder;
@override
State<StatefulBuilder> createState() => _StatefulBuilderState();
}
class _StatefulBuilderState extends State<StatefulBuilder> {
@override
Widget build(BuildContext context) => widget.builder(context, setState);
}
3、使用
用 Builder 包裹函数组件相等于创造了一个继承 StatelessWidget 的类组件;
用 StatefulBuilder 包裹函数组件相等于创造了一个继承 StatefulWidget 的类组件;
1)、Builder 示例:
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) {
return Center(
child: TextButton(
onPressed: () {
print(Scaffold.of(context).hasAppBar);
},
child: Text('hasAppBar'),
),
);
},
),
);
}
2)、StatefulBuilder 示例:
await showDialog<void>(
context: context,
builder: (BuildContext context) {
int? selectedRadio = 0;
return AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int? value) {
setState(() => selectedRadio = value);
},
);
}),
);
},
),
);
},
);
三、总结
实现很简单(为什么我之前没想到,没自己实现呢?),掌握这两个组件的使用很重要;但是实现思路和封装思维更重要;开飞机很爽,但是造飞机是更酷!