Set up AppLoading

To prove that app loading is indeed doing anything, some easy refactoring touse a loading screen are in order.

You appState has a property called isLoading. In a big app withconfiguration, that'll probably always start as 'true', and then be switchedoff when the configuration is complete. This bool is what Flutter will use torender the loading screen.

For now, the HomePage will just render a loading spinner until the configis loaded, and then it'll render with the full HomeScreen experience.

1. Add a LoadingView to HomeScreen

In your HomeScreenState widget…

  1. // screens/home_screen.dart
  2. class HomeScreen extends StatefulWidget {/*...*/}
  3. class HomeScreenState extends State<HomeScreen> {
  4. // new
  5. AppState appState;
  6. // new
  7. Widget get _pageToDisplay {
  8. if (appState.isLoading) {
  9. return _loadingView;
  10. } else {
  11. return _homeView;
  12. }
  13. }
  14. // new
  15. Widget get _loadingView {
  16. return new Center(
  17. child: new CircularProgressIndicator(),
  18. );
  19. }
  20. // new
  21. Widget get _homeView {
  22. return new Center(child: new Text(appState.user.displayName));
  23. }
  24. @override
  25. Widget build(BuildContext context) {
  26. // This is the InheritedWidget in action.
  27. // You can reference the StatefulWidget that
  28. // wraps it like this, which allows you to access any
  29. // public method or property on it.
  30. var container = AppStateContainer.of(context);
  31. // For example, get grab its property called state!
  32. appState = container.state;
  33. // Everything this build method is called, which is when the state
  34. // changes, Flutter will 'get' the _pageToDisplay widget, which will
  35. // return the screen we want based on the appState.isLoading
  36. Widget body = _pageToDisplay;
  37. return new Scaffold(
  38. appBar: new AppBar(
  39. title: new Text('Suite'),
  40. ),
  41. // Replace the hardcoded widget
  42. // with our widget that switches.
  43. body: body,
  44. );
  45. }
  46. }

This is neat. It doesn't look like much now, but you can call methods on thatvariable called container, which can call setState and tell Flutter torerender any widget in the tree that relies on that piece of state.

2. Add Loading Logic to AppStateContainer

Now, you can add logic to your app state container, which will tell the homescreen to rerender based on isLoading.

In _AppStateContainerState

  1. // app_state_container.dart
  2. class AppStateContainer extends StatefulWidget {/*..*/}
  3. class _AppStateContainerState extends State<AppStateContainer> {
  4. // Pass the state through because on a StatefulWidget,
  5. // properties are immutable. This way we can update it.
  6. AppState state;
  7. @override
  8. // Updated
  9. void initState() {
  10. super.initState();
  11. if (widget.state != null) {
  12. state = widget.state;
  13. } else {
  14. state = new AppState.loading();
  15. // fake some config loading
  16. startCountdown();
  17. }
  18. }
  19. // If all goes well, when you launch the app
  20. // you'll see a loading spinner for 2 seconds
  21. // Then the HomeScreen main view will appear
  22. Future<Null> startCountdown() async {
  23. const timeOut = const Duration(seconds: 2);
  24. new Timer(timeOut, () {
  25. setState(() => state.isLoading = false);
  26. });
  27. }
  28. // So the WidgetTree is actually
  29. // AppStateContainer --> InheritedStateContainer --> The rest of your app.
  30. @override
  31. Widget build(BuildContext context) {
  32. return new _InheritedStateContainer(
  33. data: this,
  34. child: widget.child,
  35. );
  36. }
  37. }
  38. //...

Once this is done, your app should be doing this:

gif of basic app

That's proof that your inherited widget is working, and setting stateat the proper time. Nice!