Mohammad Tabbara
Mohammad Tabbara

Reputation: 1467

Which context to use in flutter? What is the difference?

I am having trouble understanding the differences between the Widget BuildContext and the Builder BuildContext as of the following code snippets:

@override
  Widget build(BuildContext context) {

and

new Builder(
  builder: (BuildContext context){

By using the Widget BuildContext the SnackBar doesn't appear in the UI but an error is shown in the logs which indicates that the Scaffold.of() Context doesn't have a Scaffold while using the Builder context everything worked fine.

Scaffold.of(context).showSnackBar(
  new SnackBar(content: new Text('Processing Data')));

Edit: The main.dart file:

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')));
                        }
                      },
                    );
                    },
                  ),
                ),
              ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Upvotes: 1

Views: 2683

Answers (1)

Shady Aziza
Shady Aziza

Reputation: 53307

It is better if you reference the current Scaffold where you want the SnackBar to appear in by using they key property.

final GloabalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();

Scaffold(
key:_key,
...
)

show the snack bar

_key.currentState.showSnackBar(mySnackBar)

Note that each builder method gets a context to be able to reference it when using widgets that needs access to this context. In your code, the context is being confused, if you change your build method context to be something unique like (Buildcontext scaffoldContext) and then use Scaffold.of(scaffoldContext) I am not sure if this will work as I see this confusion by in Flutter quite often.

Anyway the solution above is way cleaner.

Upvotes: 3

Related Questions