Flutter 嵌套深?扩展函数了解一下,面试字节跳动 Android 工程师该怎么准备
buildItem("billy"),
],
),
),
),
);
}
Container buildItem(String name) {
return Container(
color: Colors.white,
padding: EdgeInsets.all(20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.phone),
Text(name),
],
),
);
}
}
还能不能继续优化呢?
[](
)自定义扩展函数
举个例子:想要给下面这段代码中的第 2 个Text
widget 加上marginTop:10
属性
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child: Column(
children: <Widget>[
Text('billy'),
Text('say hello'), //add margin top??
],
),
);
}
此时,我内心希望可以这样写:
显然,flutter 不支持这么写,幸运的是:[dart2.7 发布](
)时正式宣布支持扩展函数(Extension Methods)
实际上从 dart 2.6.0 就开始支持扩展函数了
如果 pubspec.yaml 中设置的 dart 版本低于 2.6.0 则会出现警告提示
如:
environment:
sdk: ">=2.1.0 <3.0.0"
警告提示:
Extension methods weren’t supported until version 2.6.0
先来定义一个扩展函数
extension WidgetExt on Widget {
Container intoContainer({
//复制 Container 构造函数的所有参数(除了 child 字段)
Key key,
AlignmentGeometry alignment,
EdgeInsetsGeometry padding,
Color color,
Decoration decoration,
Decoration foregroundDecoration,
double width,
double height,
BoxConstraints constraints,
EdgeInsetsGeometry margin,
Matrix4 transform,
}) {
//调用 Container 的构造函数,并将当前 widget 对象作为 child 参数
return Container(
key: key,
alignment: alignment,
padding: padding,
color: color,
decoration: decoration,
foregroundDecoration: foregroundDecoration,
width: width,
height: height,
constraints: constraints,
margin: margin,
transform: transform,
child: this,
);
}
}
现在,所有 widget 对象都多了一个intoContainer(...)
扩展函数,而且参数与Container
构造方法一致,于是,我们就可以这样写了:
除了Container
,其它容器也可以通过同样的方式来扩展。于是,编程体验大大提升。
还可以支持链式调用:
Text("billy")
.intoExpanded(flex: 1)
.intoContainer(color: Colors.white)
有些 widget 有多个子 widget (children), 可以添加如下的扩展函数:
extension WidgetExt on Widget {
//添加一个相邻的 widget,返回 List<Widget>
List<Widget> addNeighbor(Widget widget) {
return <Widget>[this, widget];
}
//添加各种单
child 的 widget 容器
//如:Container、Padding 等...
}
extension WidgetListExt<T extends Widget> on List<T> {
//子 List<Widget>列表中再添加一个相邻的 widget,并返回当前列表
List<Widget> addNeighbor(Widget widget) {
return this..add(widget);
}
Row intoRow({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
}) {
return Row(
key: key,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
children: this,
);
}
//添加其它多 child 的 widget 容器
//如:Column、ListView 等...
}
[](
)使用扩展函数解决嵌套过深的问题
回到本文最初的嵌套地狱,现在我们的代码可以写成这样
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo'),),
body: buildItem("amy")
.addNeighbor(buildItem("billy"),)
.intoListView()
.intoOffstage(offstage: false)
.intoContainer()
);
}
Container buildItem(String name) {
return Icon(Icons.phone)
.addNeighbor(Text(name))
.intoRow(crossAxisAlignment: CrossAxisAlignment.center,)
.intoContainer(color: Colors.white, padding: EdgeInsets.all(20),);
}
}
为了让我们的代码更加符合链式编程风格,再定义一个静态方法吧
class WidgetChain {
static Widget addNeighbor(Widget widget) {
return widget;
}
}
另外,再定义一个从数据到 widget 的映射扩展方法
extension ListExt<T> on List<T> {
List<Widget> buildAllAsWidget(Widget Function(T) builder) {
return this.map<Widget>((item) {
return builder(item);
}).toList();
}
}
现在,代码是这样的:
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo'),),
body: ["amy", "billy"]
.buildAllAsWidget((name) =>
WidgetChain
.addNeighbor(Icon(Icons.phone))
.addNeighbor(Text(name))
评论