Nerd For Tech
Published in

Nerd For Tech

When to use Dart late keyword in Flutter?

Late evening sky at the beach near my home (personal collection)

When not to use late

To put it very simply, late is not good in cases where it can accidentally blow up with LateInitializationError at runtime.

The first time I used late in Flutter app was when I tried to avoid null checks for accessing remotely loaded data from a ViewModel.

I wrote something like this:

class MyViewModel {
late SomeData someData;
bool loaded = false;
void load() async {
someData = await apiService.fetchData();
loaded = true;
}
}

Then in my view I checked if MyViewModel was loaded and only then accessed the someData to build the UI.

The problem with this approach is that it’s not fool proof. Looking at the API of MyViewModel it’s not clear what fields/methods are safe to access before loading is done and what aren’t. There needs to be some kind of custom mechanism that guarantees calling load before using the rest of MyViewModel.

Fortunately there is a much more elegant solution for handling this situation. Using different class for each state e.g loading state and success state. Then exposing these via a single state property to the view so that view does not need any null checks.

When is it good to be late

late is useful to work around the constraints on using instance methods from constructor body.

For example:

class MyBloc {
final late Subscription<MyData> _streamSubscription;
MyBloc({SomeRepository repository}) {
_streamSubscription = _repository.listen(
(value) => add(MyEvent(value))
);
}}

Notice that in this example I’m making _streamSubscription final which is pretty cool cause I know that this field should be assigned only once.

An alternative to using late here is making _streamSubscription nullable. But that is wrong. I know that it will be initialised inside the constructor body so why pollute the code with null checks?

There is one case where I might get LateInitializationError. It’s when accessing the late field inside the constructor body before it gets initialised. However, the constructor body should be small, hence easy to comprehend. Also, trying to access this field before it gets initialised is a logic error. In this case I’m ok to have the runtime error draw my attention to this potential bug (hopefully when running unit tests).

Being lazy

Another use for late is for lazy loading.

class MyClass {  final late SomeData _someData = _someComplexCalculation();}

In this case I will postpone running _someComplexCalculation until the first time I access _someData.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ürgo Ringo

Ürgo Ringo

140 Followers

Have been creating software for 20 years. Last 7 years worked as IC and team lead at (Transfer)Wise. Currently working as VP of engineering at Yummy.