Flutter: Best Practices of Calling Async Code from UI

While I think the methods mentioned by @aziza are definitely the way to go, it's worth noting that you can "roll your own" as well.

So, for example, in initState(), you could do something like this:

@override
void initState() {
    super.initState();
    _myItems = // some sane default
    FirebaseDatabase.instance.reference().child("node")
      .then((items) {
        if (widget.mounted) setState(() { _myItems = items; }
      });
}

Widget build(BuildContext context) {
  return new Scaffold(
   ///start building your widget tree
  );
}

It'd be preferable to use FutureBuilder here, but this is another way to do it (even if it's not necessarily a best practice).


In Flutter there are widgets that can help you do this seamlessly (e.g, FutureBuilder , StreamBuilder) and you can control what to be rendered based on their resolution.

Example on FutureBuilder:

Widget build(BuildContext context) {
    return new FutureBuilder(
    future: FirebaseDatabase.instance.reference().child("node"),
    builder: (BuildContext context, AsyncSnapshot snapshot) {
          return snapshot.hasData? new Scaffold(
          ///start building your widget tree
          ):new CircularProgressIndicator(); ///load until snapshot.hasData resolves to true
},);
  }

Example for StreamBuilder:

class Database {

  DatabaseReference _refProfile = FirebaseDatabase.instance.reference().child(
      "profiles");

  getProfiles() => _refProfile.onValue; }

.............

Widget build(BuildContext context) {
      return new StreamBuilder<Event>(
          stream: _database.getProfiles(), //_database = new Database()
          builder: (BuildContext context, AsyncSnapshot<Event> event) {
          return event.hasData?new Scaffold(

///build your widget tree
                    ):new CircularProgressIndicator();

/// place holder
}

It is worth mentioning that

FutureBuilder is better used when you want to fetch some data once and do not care of having consistent connection or tracking any changes in the data.

While StreamBuilder , on the other hand, enables you to keep listening to the data and you can update the state of the UI according to any update in the data.