有人可以向我解释Builder类在Flutter中的作用吗?

时间:2018-08-30 03:35:50

标签: android ios flutter

文档非常混乱和模糊。它是这样的:

Builder类

  

一个柏拉图式小部件,它调用一个闭包来获取其子小部件。

这是我的问题:

  1. “柏拉图式”是什么意思?
  2. “关闭”是什么意思?
  3. 该课程的目的是什么?

4 个答案:

答案 0 :(得分:16)

经过长时间的互联网研究,我收集了一些小片段,并将它们组合在一起,以清晰,清晰地解释了Builder类的作用。

术语:

根据官方flutter文档, Builder类定义为:

  

一个柏拉图式小部件,它调用一个闭包来获取其子小部件。

柏拉图表示这种类型的最简单的东西。术语 closure 只是 lambda 函数的另一个名称。

目的:

这将是一个冗长的解释,但是请忍受我:

在Flutter框架中,每个小部件都有一个 build 方法,该方法接受 BuildContext 参数:

  

小部件构建(   BuildContext上下文   ){   ...}

我们必须记住, 上下文 对象是由框架自动传递到小部件的 build 函数的。由于框架是自动处理的,因此没有任何理由让小部件具有需要接受 context build 之外)。 > 参数。

因此,如果您试图将特定的 context 对象传递给孩子,则将无法通过。您不能调用build()并手动传递自己的 context 对象。我的意思是,可以,但是您将两次调用build函数:

  1. 您的手动通话。
  2. 框架自动调用。

那么,如何传递特定的 context 对象?这是 Builder 类的来源。 Builder 类的目的仅仅是构建并返回子窗口小部件。这与其他任何小部件有何不同?啊哈! Builder 类使您可以将特定的 context 对象向下传递给其子级。 Builder 类基本上是您自己设置的构建函数。

我为什么需要传递特定的 context 对象?让我们看一个例子:

让我们说我们想向返回的新 Scaffold 父窗口小部件中添加一个新的 SnackBar 小部件:

 @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text(widget.title),
        ),
        body: new Container(),
        /// Scaffold doesn't exist in this context here
        /// because the context thats passed into 'build'
        /// refers to the Widget 'above' this one in the tree,
        /// and the Scaffold doesn't exist above this exact build method
        ///
        /// This will throw an error:
        /// 'Scaffold.of() called with a context that does not contain a Scaffold.'
        floatingActionButton: new FloatingActionButton(onPressed: () {
          Scaffold.of(context).showSnackBar(
                new SnackBar(
                  content: new Text('SnackBar'),
                ),
              );
        }));
  }

上面的代码无效。 Scaffold.of(context)函数将找不到 Scaffold ,因为:

  1. Scaffold 小部件尚未创建。
  2. 传递给构建函数的 context 对象引用父窗口小部件,而不是 Scaffold 小部件。

那么,我们如何让childre SnackBar小部件访问父 Scaffold 小部件?我们使用 Builder 类传递 Scaffold 小部件的上下文:

 @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Container(),
      /// Builders let you pass context
      /// from your *current* build method
      /// Directly to children returned in this build method
      ///
      /// The 'builder' property accepts a callback
      /// which can be treated exactly as a 'build' method on any
      /// widget
      floatingActionButton: new Builder(builder: (BuildContext context) {
        return new FloatingActionButton(onPressed: () {
          Scaffold.of(context).showSnackBar(
                new SnackBar(
                  backgroundColor: Colors.blue,
                  content: new Text('SnackBar'),
                ),
              );
        });
      }),
    );
  }

请记住, Builder 类的构造函数:

  

Builder({键,@ required WidgetBuilder构建器})

通过将其构件委托给通过其构造函数传递的回调函数来创建构件。

因此,在代码中:

new Builder(builder: (BuildContext context){ ... });

我们提供了一个闭包,

  1. 包含一个 BuildContext上下文 参数
  2. 根据传递的 context 构建并返回子窗口小部件。

基本上,您提供了自己的构建功能。此闭包中的 BuildContext上下文参数是Scaffold的上下文!宝贝!

基本上就是这样。 Flutter文档完全没有提供完整的解释。我觉得比破译Flutter文档,破译古代象形文字要容易得多。

我希望这对目前正在学习Flutter的单调乏味的人有所帮助。

答案 1 :(得分:4)

简单定义?

这个Builder小部件就像它的名字所暗示的那样;用于创建带有“新上下文”的子窗口小部件。

技术定义?

此构建器具有 builder属性,并且此属性接受 WidgetBuilder typedef (WidgetBuilder typedef是用于使用新上下文创建(返回)窗口小部件的函数的签名)< / p>

如果您想了解 WidgetBuilder typedef ,请使用此链接➡{https://api.flutter.dev/flutter/widgets/WidgetBuilder.html

用法:


1 。当 Scaffold小部件 Scaffold.of方法在同一构建方法中时。

[当时scaffold.of方法找不到壁橱Scaffold小部件,因为两者都是 在 相同的上下文,通过在build方法内创建新的上下文,您可以解决此问题,这就是为什么 我们使用Builder Widget来创建带有New BuildContext的控件。 ]

下面的代码显示了想要在同一构建方法use

中使用 Scaffold.of Scaffold 小部件时Builder小部件的实际用法。

(仔细查看这些注释,它将帮助您理解上下文

Widget build(BuildContext context) {                       // context - 1
  return Scaffold(
    appBar: AppBar(
      title: Text('Demo')
    ),
    body: Builder(
      // Create an inner BuildContext so that the onPressed methods
      // can refer to the Scaffold with Scaffold.of().
      builder: (BuildContext context) {                    // context - 2
        return Center(
          child: RaisedButton(
            child: Text('SHOW A SNACKBAR'),
            onPressed: () {
              Scaffold.of(context).showSnackBar(SnackBar(  // here context is (context- 2)
                content: Text('Have a snack!'),
              ));
            },
          ),
        );
      },
    ),
  );
}

2 。当 Theme.of 方法和 Theme 小部件处于同一构建方法中时。

[此处的目的也与上述1相同]

下面的代码显示了当您要在同一构建方法use

中使用 Theme.of Theme 小部件时,Builder小部件的实际用法。
@override
Widget build(BuildContext context) {
  return MaterialApp(
    theme: ThemeData.light(),
    body: Builder(
      // Create an inner BuildContext so that we can refer to
      // the Theme with Theme.of().
      builder: (BuildContext context) {
        return Center(
          child: Text(
            'Example',
            style: Theme.of(context).textTheme.title,
          ),
        );
      },
    ),
  );
}


额外点

我们可以在许多实例上看到的

buider属性(WidgetBuilder typedef)

在该代码部分的下方显示,“ MaterialPageRoute ”如何使用构建器属性获取该路线的小部件

Navigator.push(context, MaterialPageRoute<void>(
  builder: (BuildContext context) {                 //here
    return Scaffold(
      appBar: AppBar(title: Text('My Page')),
      body: Center(
        child: FlatButton(
          child: Text('POP'),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ),
    );
  },
));

答案 2 :(得分:3)

它基本上将将构建窗口小部件的功能转换为窗口小部件。

在需要传递小部件但仅具有返回小部件的功能的地方,可以使用Builder小部件。

bool bar;

Widget createFooOrBarWidget() {
  if(bar) {
    return BarWidget();
  } 
  return FooWidget();
}

Widget build(BuildContext context) =>
  Container(child: Builder((context) => createFooOrBarWidget()));

您也可以使用

Widget build(BuildContext context) =>
  Container(child: createFooOrBarWidget());

但是前者会延迟Foo或Bar小部件的创建,直到实际调用build为止。

答案 3 :(得分:0)

observation: you might like to give the inner context arg a different name in order to reinforce the fact that it is the one passed to the FAB, i.e. the buildContext actually corresponds to a widget's parent, which is why Scaffold.of(context passed to FAB) => scaffold widget.

Hmm this stuff is a real learning curve for old GWT devs, but moving from Java to Dart is definitely a huge step fwd. Thanks for your work here.