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

Wal*_*r M 19 android ios flutter

该文档非常混乱和模糊。它说的是:

建造者类

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

这是我的问题:

  1. 他们所说的“柏拉图式”是什么意思?
  2. “封闭”是什么意思?
  3. 本课程的目的是什么?

Wal*_*r M 53

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

术语:

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

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

柏拉图式意味着最简单的东西。术语闭包只是lambda函数的别称。

目的:

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

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

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

我们必须记住,上下文对象是由框架自动传递给小部件的build函数的。由于该框架会自动进行处理,因此没有任何理由让小部件具有需要接受上下文参数的构造函数或函数(除了build之外)。

因此,如果您尝试将特定的上下文对象传递给孩子,则将无法进行操作。您不能调用build()并手动传递自己的上下文对象。我的意思是,可以,但是您将两次调用build函数:

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

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

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

假设我们要向返回的新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'),
                ),
              );
        }));
  }
Run Code Online (Sandbox Code Playgroud)

上面的这段代码不起作用。该Scaffold.of(上下文)函数将无法找到脚手架,因为:

  1. 支架部件还没有被创建。
  2. 传递给构建函数的上下文对象引用父窗口小部件,而不是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'),
                ),
              );
        });
      }),
    );
  }
Run Code Online (Sandbox Code Playgroud)

记住,Builder类的构造函数:

生成器({密钥,@ required WidgetBuilder生成器})

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

因此,在代码中:

new Builder(builder: (BuildContext context){ ... });
Run Code Online (Sandbox Code Playgroud)

我们提供了一个关闭:

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

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

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

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

  • 感谢您进行研究并发布如此清晰的解释。这非常有帮助!所有关于 Builder 的 Flutter 文档都是“一个柏拉图式的小部件,调用闭包来获取其子小部件”。近乎无用! (14认同)
  • 我认为这里的用词可能会产生误导。我不会说你用它来“传递特定的上下文”,这可能被理解为“你想要的任何上下文”,而事实上它是由框架控制的,并且总是比它周围的上下文更深的上下文。 (3认同)

Dil*_*han 9

简单定义

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

技术定义

这个 Builder 有一个builder 属性,这个属性接受WidgetBuilder typedef(WidgetBuilder typedef 是一个函数的签名,该函数创建(返回)一个具有新上下文的小部件)

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

用法:


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

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

下面的代码显示了 Builder 小部件的实际用法,当您想在相同的构建方法中使用Scaffold.ofScaffold小部件时

(仔细看这些评论——它会帮助你理解上下文

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!'),
              ));
            },
          ),
        );
      },
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

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

[这里的目的也与上述1相同]

下面的代码显示了 Builder 小部件的实际用法,当您想在相同的构建方法中使用Theme.ofTheme小部件时

@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,
          ),
        );
      },
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

加分

我们可以在许多实例上看到 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);
          },
        ),
      ),
    );
  },
));
Run Code Online (Sandbox Code Playgroud)


Gün*_*uer 8

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

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

bool bar;

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

Widget build(BuildContext context) =>
  Container(child: Builder((context) => createFooOrBarWidget()));
Run Code Online (Sandbox Code Playgroud)

你也可以使用

Widget build(BuildContext context) =>
  Container(child: createFooOrBarWidget());
Run Code Online (Sandbox Code Playgroud)

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

  • 好的。确认后,我将根据您的信息和我为找到 Builder 类的清晰解释所做的 23 小时研究发布我自己问题的答案。在我发布答案时给我几分钟时间,看看我是否做对了。 (2认同)