How to check 'late' variable is initialized in Dart How to check 'late' variable is initialized in Dart dart dart

How to check 'late' variable is initialized in Dart


Unfortunately this is not possible.

From the docs:

AVOID late variables if you need to check whether they are initialized.

Dart offers no way to tell if a late variable has been initialized orassigned to. If you access it, it either immediately runs theinitializer (if it has one) or throws an exception. Sometimes you havesome state that’s lazily initialized where late might be a good fit,but you also need to be able to tell if the initialization hashappened yet.

Although you could detect initialization by storing the state in alate variable and having a separate boolean field that tracks whetherthe variable has been set, that’s redundant because Dart internallymaintains the initialized status of the late variable. Instead, it’susually clearer to make the variable non-late and nullable. Then youcan see if the variable has been initialized by checking for null.

Of course, if null is a valid initialized value for the variable, thenit probably does make sense to have a separate boolean field.

https://dart.dev/guides/language/effective-dart/usage#avoid-late-variables-if-you-need-to-check-whether-they-are-initialized


You can create a Late class and use extensions like below:

import 'dart:async';import 'package:flutter/foundation.dart';class Late<T> {  ValueNotifier<bool> _initialization = ValueNotifier(false);  late T _val;    Late([T? value]) {    if (value != null) {      this.val = value;    }  }  get isInitialized {    return _initialization.value;  }  T get val => _val;  set val(T val) => this    .._initialization.value = true    .._val = val;}extension LateExtension<T> on T {  Late<T> get late => Late<T>();}extension ExtLate on Late {  Future<bool> get wait {    Completer<bool> completer = Completer();    this._initialization.addListener(() async {      completer.complete(this._initialization.value);    });    return completer.future;  }}

Create late variables with isInitialized property:

var lateString = "".late;var lateInt = 0.late;//orLate<String> typedLateString = Late();Late<int> typedLateInt = Late();

and use like this:

print(lateString.isInitialized)print(lateString.val)lateString.val = "initializing here";

Even you can wait for initialization with this class:

Late<String> lateVariable = Late();lateTest() async {  if(!lateVariable.isInitialized) {    await lateVariable.wait;  }  //use lateVariable here, after initialization.}


Someone may kill you if they encounter it down the road, but you can wrap it in a try/catch/finally to do the detection. I like it better than a separate boolean.

We have an instance where a widget is disposed if it fails to load and contains a late controller that populates on load. The dispose fails as the controller is null, but this is the only case where the controller can be null. We wrapped the dispose in a try catch to handle this case.