Flutter: build and createState for Stateful Widgets

Derek Lakin
Aug 16, 2018 · 3 min read

Caveat: I’d still consider myself to be pretty new to Flutter, so apologies if I’m saying something that everyone else considers to be common knowledge :)

I’ve just finished debugging an issue in my app and thought I’d share what I found. The app has a home screen with a TabBarView on it. One tab is a Timeline widget (which is just a custom Stepper) containing a number of items and the other tab is essentially a ListView. The user can tap on a FloatingActionButton to open a new page and create new items that are then populated on the Timeline.

I’m also using Flutter Redux for state management. So when the state changes, a new view model is created for the Home page, which is passed to the builder for the Home page. The widget tree is rebuilt, which results in a call to build on each widget. So we get something like:

HomePage.build -> 
HomePageViewModel() ->
Timeline(homePageViewModel) ->
Timeline.createState()
TimelineState(homePageViewModel) ->
Timeline.build()

In the Timeline widget (which is a StatefulWidget), I’m using the HomePageViewModel to get the items to display and this is where it got tricky. My initial approach looked something like this:

class Timeline extends StatefulWidget {
final HomePageViewModel _viewModel;
Timeline(this._viewModel);
@override
State<Timeline> createState() {
return TimelineState(this._viewModel);
}
}
class TimelineState extends State<Timeline> {
final HomePageViewModel _viewModel;
TimelineState(this._viewModel);
@override
void build() {
// Build the items from this._viewModel.Items;
}
}

Seems perfectly reasonable, right? Every time the widget tree gets rebuilt, our Timeline widget is newly created, and so we rebuild with the latest HomePageViewModel. WRONG! When the widget tree is rebuilt, the build method will be called each time, but createState will NOT unless setState is called explicitly (or the widget is removed from or moved in the widget tree).

State is information that (1) can be read synchronously when the widget is built and (2) might change during the lifetime of the widget. It is the responsibility of the widget implementer to ensure that the State is promptly notified when such state changes, using State.setState.

So, in my case, the application state change was recreating the Timeline widget, but the TimelineState object remained unchanged until a setState further up the widget tree was called (such as changing tabs).

There are essentially three options to resolve this:

  1. Use a StatelessWidget instead (unlikely to be an option if you deliberately went down the stateful route).
  2. Ensure that setState is called when your application state changes.
    This wasn't an option for me since I’m using flutter_redux.
    UPDATE: Having re-read the documentation for flutter_redux, I think this is actually the correct option and you do so by using a StoreConnector in any widget that needs to respond to app state changes.
  3. Access the view model from the widget instead of passing it into the state:
class Timeline extends StatefulWidget {
final HomePageViewModel _viewModel;
Timeline(this._viewModel);
@override
State<Timeline> createState() {
return TimelineState();
}
}
class TimelineState extends State<Timeline> {
TimelineState();
@override
void build() {
// Build the items from widget._viewModel.Items;
}
}

The State class that we’re inheriting from helpfully exposes a widget property, which we can use to access the related widget and the _viewModel within, which is passed in fresh every time the widget is re-created. Problem solved! :)


The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.

Derek Lakin

Written by

The seemingly random musings of a Senior Engineering Manager at Culture Trip.

FlutterPub

The Pub(lication) for all about the Flutter and its magic

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade