Mobile 在颤振中使用哪种上下文?有什么区别?

Mobile 在颤振中使用哪种上下文?有什么区别?,mobile,flutter,Mobile,Flutter,对于以下代码片段,我无法理解小部件BuildContext和构建器BuildContext之间的区别: @override Widget build(BuildContext context) { 及 通过使用Widget BuildContext,SnackBar不会出现在UI中,但日志中会显示一个错误,表明Scaffold.of()Context在使用Builder Context时没有Scaffold Scaffold.of(context).showSnackBar( new

对于以下代码片段,我无法理解
小部件BuildContext
构建器BuildContext
之间的区别:

@override
  Widget build(BuildContext context) {

通过使用
Widget BuildContext
,SnackBar不会出现在UI中,但日志中会显示一个错误,表明
Scaffold.of()Context
在使用
Builder Context
时没有Scaffold

Scaffold.of(context).showSnackBar(
  new SnackBar(content: new Text('Processing Data')));
编辑:main.dart文件:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'APP'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  final formKey = new GlobalKey<FormState>();
  String username;
  @override
  //This context
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            new Flexible(
              child: new Container(
                child: new Center(
                  child: new Text(widget.title),
                ),
              ),
              flex: 1,
            ),
            new Form(
              key: formKey,
              child:
              new Row(children: <Widget>[
                new Flexible(child:
                  new Container(
                    margin: EdgeInsets.zero,
                    child: new TextFormField(
                      decoration:
                      new InputDecoration(
                        hintText: 'Username',
                        labelText: "1",
                        labelStyle: new TextStyle(color: new Color.fromARGB(255, 0, 0, 0)),
                      ),
                      validator: (val) => val.isEmpty? 'Username can\'t be empty.' : null,
                      ),
                  ),
                  flex: 1,
                ),
                new Flexible(child:
                  new Container(
                    margin: EdgeInsets.only(
                      left: 8.0,
                      right: 8.0,
                    ),
                    child: new TextFormField(
                      decoration: new InputDecoration(
                        border: InputBorder.none,
                        hintText: "Password",

                      ),
                      validator: (val) => val.isEmpty? 'Password can\'t be empty.' : null,
                      obscureText: true,
                    ),
                  ),
                  flex: 1,
                ),
                new Container(
                  child:
                  new Builder(
                    //And this context
                    builder: (BuildContext context){
                    return RaisedButton(
                      child: new Text("Sign in"),
                      onPressed: (){
                        if (formKey.currentState.validate()) {
                          // If the form is valid, display a snackbar. In the real world, you'd
                          // often want to call a server or save the information in a database
                          Scaffold.of(context).showSnackBar(
                          new SnackBar(content: new Text('Processing Data')));
                        }
                      },
                    );
                    },
                  ),
                ),
              ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(新的MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回新材料PP(
标题:“颤振演示”,
主题:新主题数据(
主样本:颜色。蓝色,
),
主页:新MyHomePage(标题:“应用程序”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>new_MyHomePageState();
}
类_MyHomePageState扩展状态{
final formKey=new GlobalKey();
字符串用户名;
@凌驾
//这一背景
小部件构建(构建上下文){
返回新材料PP(
家:新脚手架(
正文:新栏目(
crossAxisAlignment:crossAxisAlignment.center,
mainAxisSize:mainAxisSize.max,
mainAxisAlignment:mainAxisAlignment.start,
儿童:[
新柔性(
子容器:新容器(
孩子:新中心(
子项:新文本(widget.title),
),
),
弹性:1,
),
新形式(
key:formKey,
儿童:
新行(儿童:[
新的灵活(儿童:
新容器(
边距:EdgeInsets.zero,
子项:新建TextFormField(
装饰:
新输入装饰(
hintText:'用户名',
标签文字:“1”,
labelStyle:new TextStyle(颜色:new color.fromARGB(255,0,0,0)),
),
验证程序:(val)=>val.isEmpty?“用户名不能为空。”:null,
),
),
弹性:1,
),
新的灵活(儿童:
新容器(
页边距:仅限边距(
左:8.0,
右图:8.0,
),
子项:新建TextFormField(
装饰:新的输入装饰(
边框:InputBorder.none,
hintText:“密码”,
),
验证程序:(val)=>val.isEmpty?“密码不能为空。”:null,
蒙昧文字:对,
),
),
弹性:1,
),
新容器(
儿童:
新建筑商(
//在这种背景下
生成器:(BuildContext上下文){
返回上升按钮(
子项:新文本(“登录”),
已按下:(){
if(formKey.currentState.validate()){
//如果表单有效,则显示一个snackbar
//通常需要调用服务器或将信息保存在数据库中
Scaffold.of(上下文).showSnackBar(
新SnackBar(内容:新文本(“处理数据”));
}
},
);
},
),
),
],
),
),
],
),
),
);
}
}

如果您使用
属性引用当前的
Scaffold
,您希望
SnackBar
显示在其中,则效果会更好

final GloabalKey _key=GlobalKey()

带我去小吃店

_key.currentState.showSnackBar(mySnackBar)
请注意,每个生成器方法都会获得一个
上下文
,以便在使用需要访问此上下文的小部件时能够引用它。在您的代码中,
上下文
被混淆了,如果您将
构建
方法
上下文
更改为像
(Buildcontext scaffoldContext)
这样独特的方法,然后使用
Scaffold.of(scaffoldContext)
我不确定这是否有效,因为我经常看到这种混淆


无论如何,上面的解决方案更干净

您能否放置代码,以便我们能够清楚地了解Widget BuildContext和Builder BuildContext。我添加了该文件并在上下文上方进行了注释
Builder方法获得一个上下文以能够引用它
您的意思是,每个Builder或widger都有自己的上下文,与Java中的每个活动(流程)不同吗有它的上下文吗?我不了解Java,但您只需要能够使用BuildContext并代表您正在调用的上下文做一些事情(在这种情况下调用顶级方法,如showSnackbar或showDialogue..等),您会发现调用父主题从中读取一些数据时使用了相同的方法(InheritedWidget)。您可能需要参考文档以获得完整的解释:
Scaffold(
key:_key,
...
)
_key.currentState.showSnackBar(mySnackBar)