Flutter Widget 之Builder

357 阅读2分钟

大多数情况下Flutter中的部件在构建时不会查找父控件的额外信息

Widget build(BuildContext context) {
    return ListView(
        children: <Widget>[
           One(),
           Two(
               child: Three(),
           ),
        ],
    );
}

但有时,编码时会遇到的一些状况是相同BuildMethod下子部件需要存取父部件中的BuildContext

Widget build(BuildContext context) {
    return Scaffold(
        body: RaisedButton(onPressed: (){
        Scaffold.of(context).showSnackBar(
                SnackBar(content: Text('Help!')),
        );
        
    });
}

image.png

这就是Builder部件的用途

需要存取InheritedWidget时就会遇到这种情形,例如Scaffold、Navigator ThemeData、MediaQuery或部分状态管理的方法

Widget build(BuildContext context) {
    return Scaffold(
        body: RaisedButton(onPressed: (){
        Scaffold.of(context).showSnackBar(
                SnackBar(content: Text('Help!')),
        );
        
    });
}
Widget build(BuildContext context) {
    return MaterialApp(
        home: RaisedButton(
            // Help! This doesn't work
            onPressed: () => Navigator.of(context).push(MyPageRoute()),
            // Could also be written;
            //Navigator.push(context, MyPageRoute());
        );
    );
}
Widget build(BuildContext context) {
    return Provider<MyState>(
        builder: (_) => MyState(),
        child: Text(
            //Help!
            Provider.of<MyState>(context).text
        ),
    );
}

最常用来判断是否遇到此情况的方式就是看看函式中是否为查找相同Build()下特定widget 的咨询写入和“of()”调用指令

MediaQuery.of(context).size

有个解决办办法就是将子部件数抽离成为本身另有Build()的独立widget中

Scaffold(
    body: RaisedButton(onPressed: (){
        Scaffold.of(context).showSnackBar(
            SnackBar(content: Text('Help!')),
        );
    }),
);
Scaffold(
    body: ScaffoldButton(),
);

class ScaffoldButton extends StatelessWidget {
    Widget build(BuildContext context) {
        return RaisedButton(onPressed: (){
            Scaffold.of(context).showSnackBar(
                SnackBar(content: Text('Much Better')),
            );
        };
    }
}

不过有时候,这会使其中一个Build()变得如此微小或简单,因此将其分离为独立widget感觉很笨

Widget build(BuildContext context) {
    // Really simple build method!
    // Why is this a stand-alone class?
    return Scaffold(body: ScaffoldButton());
}

这时Builder部件便派上用场,只需将Builder以wrap传入,任何子部件需要构建当前节点(context)的地方以利存取父部件的内容,这样就可以了!

Widget build(BuildContext context) {
    return Scaffold(
        body: Builder(
            builder: (BuilderContext context) {
                return RaisedButton(onPressed:(){
                    Scaffold.of(context).showSnackBar(
                        SnackBar(content: Text('Great!')),
                    );
                }):
            }
        ),
    );
}

与其他闭包(closure)非常类似,Builder将确保父部件优先建置好以利子部件的当前节点(context)查找。

当调用传到Builder部件的builder函数时子部件树就会随之构建。

但要提醒各位为此子部件创造独立部件也可达到完全相同的结果。Builder是个能在需要时提供最新BuildContext类的简单部件

如果想了解有关Builder的内容,或者关于Flutter的其他功能,请访问flutter.dev

原文翻译自视频:视频地址