/ snippet

Run async operation on widget creation

I often see people trying to execute an asyncronous operation in the render method of a widget. This doesn't work, but is also bad because it gets called every time the state or properties get updated. It can lead to a lot of unneccessary work. A StatefulWidget needs to be used to do this properly.

class MyWidget extends StatefulWidget {
    @override
    State createState() => new MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
    var _result;

    @override
    void initState() {
        // This is the proper place to make the async calls
        // This way they only get called once

        // During development, if you change this code,
        // you will need to do a full restart instead of just a hot reload
        
        // You can't use async/await here,
        // We can't mark this method as async because of the @override
        loadAsyncData().then((result) {
            // If we need to rebuild the widget with the resulting data,
            // make sure to use `setState`
            setState(() {
                _result = result;
            });
        });
    }
    
    @override
    Widget build(BuildContext context) {
        if (_result == null) {
            // This is what we show while we're loading
            return new Container();
        }
        
        // Do something with the `_result`s here
        return new ResultWidget(_result);
    }
}

In summary,

  1. Use a StatefulWidget
  2. Make the asyncronous call inside initState
  3. Make sure to call setState with the result, if we need to rerender
  4. Do something meaningful with the results :)

Brian Armstrong

A web application developer with 15+ years programming experience. Flutter evangelist, React.js enthusiast.

Read More