Given the asynchronous nature of the Flutter shared_prefs plugin, how could one make sure that when an app is launched the correct theme settings are immediately displayed? I.e. no flash of the default theme followed by applying the correct theme once the shared_prefs have finished loading.


Solution 1: Eric Seidel

One way would be to delay the display of your main app with a loading screen. A pattern I've seen is:

main() async {
  runApp(new LoadingScreen());
  runApp(new App(await asyncStuff()));
}

You can call runApp as often as you like: https://api.flutter.dev/flutter/widgets/runApp.html


Solution 2: Collin Jackson

When your build method requires waiting for a Future, it's a good time to break out FutureBuilder.

void main() {
  runApp(new FutureBuilder(
    future: SharedPreferences.getInstance(),
    builder: (_, snapshot) {
      return snapshot.hasData ?
             new MyApp(preferences: snapshot.data) :
             new LoadingScreen(); 
    },
  ));
}

A few tips for building apps with this pattern:

  • SharedPreferences.getInstance() is pretty fast. You app may look better with an empty Container as a black loading screen instead of a flash of colorful content. However, if you're loading other stuff at the same time, showing your logo makes more sense.

  • If you need to await multiple futures, you can use Future.wait or nest multiple FutureBuilders together.


Solution 3: Luke

You can also use a StatefulWidget with setState to update the root widget after the application configuration is complete.

You can use something like (in short):

@override
Widget build(BuildContext context) {
    _return mainWidget;
}

In conjunction with:

mainWidget = loadingWidget();
someMethodThatDoesAppConfig().then((Widget configuredWidget) {
    setState(() {
        _mainWidget = configuredWidget;
    });
});