skip to Main Content

After switching the application to null safety support, the part of the code that is responsible for unlogging stopped working with an error:

LateInitializationError: Field ‘_keepAliveTimer@44195927’ has not been
initialized.

class _TabPageState extends State<TabPage> with SingleTickerProviderStateMixin {
  late TabController tabController;

  @override
  void initState() {
    super.initState();
    _startKeepAlive(); // initialization
    tabController = TabController(length: 4, vsync: this);
  }
  ...


void _startKeepAlive() {
    final observer = _KeepAliveObserver();
    // assert(observer._keepAliveTimer == null);
    observer._keepAlive(true); // errrrrrror
    WidgetsBinding.instance.addObserver(observer);
  }

class _KeepAliveObserver extends WidgetsBindingObserver {
  final _inactivityTimeout = const Duration(seconds: 30);
  late Timer? _keepAliveTimer;

  void _keepAlive(bool visible) {
    _keepAliveTimer?.cancel();
    if (visible) {
      _keepAliveTimer = null;
    } else {
      _keepAliveTimer = Timer(_inactivityTimeout, () {
        GetIt.instance<LocalStorageService>().resetPassword();
        exit(0);
      });
    }
  }

The location of the error is shown by a comment.
How to fix it?

2

Answers


  1. The conditional member access operator (?.) is used to access a member of an instance if it’s not null, and do nothing (and returns null) if the instance is null. It does not prevent error that is caused by late variable not initialized yet.

    The late keyword is used to promise that a variable will already be initialized at the time it’s being used. Since your variable is already nullable, you don’t need to put the late keyword.

    Login or Signup to reply.
  2. First, in general, you should avoid late vars the more you can. That’s because, they can produce errors with like you have.

    Once this said, if you really need to have one, you should protect your late vars with test to ensure they are not null.

    And for Timers, you should check if they are running before trying to cancel them.

    So your function could be:

      void _keepAlive(bool visible) {
        if (_keepAliveTimer != null && _keepAliveTimer.isActive) {
            _keepAliveTimer.cancel();
        }
    
        if (visible) {
          _keepAliveTimer = null;
        } else {
          _keepAliveTimer = Timer(_inactivityTimeout, () {
            GetIt.instance<LocalStorageService>().resetPassword();
            exit(0);
          });
        }
       }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search