Thank-you, Ray.

Ah, yes. That’s the question, isn’t it.

In my own experience, the best practice is to assume you’re to always work with a ‘Future’ object of SharedPrefs (i.e. you must use await & async & then), but have an implementation that will take advantage of an instance of SharedPrefs if it’s available.

In other words, use this class library. :)

Every ‘get’ function with a capital ‘F’ will use an instance of SharedPrefs if it’s available. However, if null, then the ‘await’ is there to save the day. Below is the Prefs.getStringF(String key) async for example:

String value;
if (_prefsInstance == null) {
var instance = await _prefs;
value = instance.getString(key) ?? "";
} else {
value = getString(key);
return value;

As you’ve hinted, I’ve seen a FutureBuilder used in the main() to display a ‘Loading Screen’ while, for example, the SharedPreference and what have you are ‘initialized’ in App.init();

void main() {

future: App.init(),
builder: (_, snapshot) {
return snapshot.hasData ? MyApp() : LoadingScreen();

Conceivably, with regards to this particular class library, you could call its ‘init’ in the main.dart file before you do anything else. A dirty approach though. Frankly, no guarantee its instantiated in time.

import ‘package:prefs/prefs.dart’;void main() {


That’s why when my apps are starting up, I’m using the ‘F versions’ to get any preferences that are needed…at start up.


When the app has finished ‘starting up’ and is now waiting for user interaction, it’s then (when the user clicks on an ‘app setting’ in some menu, for example) I’m assured a ‘instantiated’ SharedPreference is available:

var theme = Prefs.getString('theme');

Freelance Developer

Freelance Developer