Flutter

使用 `Nested` 处理 flutter 嵌套过深

2021-09-02  本文已影响0人  李小轰
背景

我们知道flutter是一种声明式的开发模式。编写代码时,widget一层嵌套一层,最后在Render层进行整理汇总后,完成绘制。这种嵌套的设计模式,在视觉上,往往会让我们产生疲惫感。

嵌套现象

如下,我们声明三个Widget,并把它们三个进行嵌套排列:

///第一层父节点
class AWidget extends StatefulWidget {
  final Widget child;

  const AWidget({Key key, @required this.child}) : super(key: key);

  @override
  _AWidgetState createState() => _AWidgetState();
}

class _AWidgetState extends State<AWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(10),
      color: Colors.blue,
      child: widget.child,
    );
  }
}
///第二层父节点
class BWidget extends StatelessWidget {
  final Widget child;

  const BWidget({Key key, @required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(10),
      color: Colors.yellow,
      child: child,
    );
  }
}
///第三层子节点
class CWidget extends StatelessWidget {
  const CWidget({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text("child C");
  }
}
///嵌套排列
Widget body() {
  return AWidget(
    child: BWidget(
      child: CWidget(),
    ),
  );
}

我们发现,在嵌套层数不多时,代码阅读性并没有受到太大的影响。但当嵌套关系变得复杂时,会严重影响编码体验。

处理 flutter 嵌套过深的利器 Nested

Nested 传送门

使用方式

我们使用Nested对上面的Demo进行优化修改:

///第一层父节点
class AWidget extends SingleChildStatefulWidget {
  const AWidget({Key key}) : super(key: key);

  @override
  _AWidgetState createState() => _AWidgetState();
}

class _AWidgetState extends SingleChildState<AWidget> {
  @override
  Widget buildWithChild(BuildContext context, Widget child) {
    // 这里接收到的 child 就是 BWidget
    return Container(
      padding: EdgeInsets.all(10),
      color: Colors.blue,
      child: child,
    );
  }
}
///第二层父节点
class BWidget extends SingleChildStatelessWidget {
  const BWidget({Key key}) : super(key: key);

  @override
  Widget buildWithChild(BuildContext context, Widget child) {
    // 这里接收到的 child 就是 CWidget
    return Container(
      padding: EdgeInsets.all(10),
      color: Colors.yellow,
      child: child,
    );
  }
}

继承后,需要实现 buildWithChild 方法,方法内 child 入参是 Nested 框架层处理注入的子节点[ 分别是 demo 中的 CWidget 和 BWidget ]。(实现原理我们在文末来聊)

Widget body() {
  return Nested(
    children: [
      AWidget(),
      BWidget(),
    ],
    child: CWidget(),
  );
}
代码说明:

按照倒序关系:

CWidget 作为 child 响应在 BWidgetbuildWithChild 方法中;
BWidget 作为 child 响应在 AWidgetbuildWithChild 方法中。
注意点: Nestedchildren 数组要求元素必须是 SingleChildWidget的子类

开发便利贴:

Nested 为我们提供如下工具类,已实现继承SingleChildWidget。前两种方式需要基础并重写buildWithChild方法。


Nested 实现原理分析

Nested结构简图
简单来说,Nested 在 build 方法中,倒序遍历 children ,将每个 item 转换成 _NestedHook 对象。
并在遍历的过程中,将倒序排序中的前节点(我们后面所说的子节点)注入到每个 item 里面。第一个 item 注入的是 Nestedchild 对象,其他 item 注入的是children队列中的前一个节点元素。
最终,注入的 child ,会响应在各自 buildWithChild 方法中,作为入参存在。
我们用 Demo 中的样例画了一张简图,整个过程更加清晰:

我们常用的 provider bloc 这两个库也是使用的 Nested 来处理代码的嵌套深渊

关于Flutter嵌套优化,小轰看到过另一种思路,这里也分享给大家 Flutter嵌套优化

上一篇下一篇

猜你喜欢

热点阅读