Mindflow: Flutter deal with Future! in 6 Steps

With a Swift background, Flutter+Dart require a different thought-process. Future<T> is associated with async calls and it could be hard to re-route your brain in a one go. In this article I am sharing my experience on how the mindflow when dealing with Future<T> using SharePreferences as an example, from start to a 1-liner in 6 steps.

1. Direct mindflow:

This is how a method looks like with the consideration of existing of Future<T>, it doesn’t work since SharedPreferences.getInstance() returns Future<SharedPreferences> instead of SharedPreferences.

static int getCount(){

// This will return Future<SharedPreferences>, unwarp is needed.
final preferences = SharedPreferences.getInstance();

// Future<SharedPreferences> causes error
// because SharedPreferences has .getInt()
// but Future<SharedPreferences> does not have .getInt()
final value = preferences.getInt("attributeName");

return value;
}

2. Fix the Future!

To handle Future<SharedPreferences>, add async and await. But the value can be null!

// async is needed to use the keyword await
// async also require Future<int> instead of int
static Future<int> getCount() async {

// Keyword await "unwarp" Future<SharedPreferences> to SharedPreferences
final preferences = await SharedPreferences.getInstance();

// .getInt() works normally now,
// but null can be return if "attributeName" does not have a value
final value = preferences.getInt("attributeName");

return value;
}

3. Fix the null value!

Change the final to var for value to be validated:

// async is needed to use the keyword await
static Future<int> getCount() async {

// Good now
final preferences = await SharedPreferences.getInstance();

// Change final to var so value can be validated
var value = preferences.getInt("attributeName");

// Validating value
if (value == null){
value = 0;
}

return value;
}

4. Shorthand for if …

if … could be a bit blocky, we could replace it with (condition) ? (true) : (false):

static Future<int> getCount() async {

// Shortent this too
final pref = await SharedPreferences.getInstance();

// Replace if with (condition) ? (true) : (false)
var value = pref.getInt("attributeName") == null ? 0 : pref.getInt("attributeName");

return value;
}

5. Remove more

Future<T> can be stacked with (await Future<T>) to get T within the async method.

static Future<int> getCount() async {

// Remove this line too

// Replace it with (await Future<SharedPreferences>) to get SharedPreferences
var value = (await SharedPreferences.getInstance()).getInt("attributeName") == null ? 0 : (await SharedPreferences.getInstance()).getInt("attributeName");

return value;
}

6. One-liner!

1-liner, just return the value :

static Future<int> getCount() async {
return (await SharedPreferences.getInstance()).getInt("attributeName") == null ? 0 : (await SharedPreferences.getInstance()).getInt("attributeName");
}