Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null check operator used on a null value with allReady on hot refresh #345

Closed
martyfuhry opened this issue Sep 29, 2023 · 2 comments
Closed

Comments

@martyfuhry
Copy link

I'm using allReady in one of my widgets. One of the services I've registered fails to complete in the timeout (which isn't the fault of this package), so the function errors out.

@override
Widget build(BuildContext context) {
  allReady(
    onReady: (context) {
      // ready! do something like navigate somewhere else
      context.go('/home');
    },
    onError: (context, error) {
      // handle a startup error
      print('error $error');
    },
    timeout: const Duration(seconds: 3),
  );
  
  return Center(child: Text('Loading!'));
}

When I run this, I correctly see the error printed out. You could reproduce this with a particular service (using injectable):

@singleton
Future<MyService> myService()
    => Future.delayed(Duration(seconds: 4))
           .then((_) => MyService());

When I hot refresh, I get the error:

The following _TypeError was thrown building MyApp(dirty):
Null check operator used on a null value

When the exception was thrown, this was the stack:
#0      _WatchItState.allReady (package:watch_it/src/watch_it_state.dart:513:11)
#1      allReady (package:watch_it/src/watch_it.dart:430:8)
...

Looking at the source for that file:

return registerFutureHandler<Object, bool>(
  handler: (context, x, dispose) {
    if (x.hasError) {
      onError?.call(context, x.error);
    } else {
      onReady?.call(context);
      if (shouldRebuild) {
        (context as Element).markNeedsBuild();
      }
    }
    dispose();
  },
  allowMultipleSubscribers: false,
  initialValueProvider: () => GetIt.I.allReadySync(),

  /// as `GetIt.allReady` returns a Future<void> we convert it
  /// to a bool because if this Future completes the meaning is true.
  futureProvider: () =>
      GetIt.I.allReady(timeout: timeout).then((_) => true),
).data!;

In particular, it's the data! null check operator which is throwing the exception. Am I using the allReady incorrectly or should there be some additional null checking in the allReady function?

Thank you.

@escamoteur
Copy link
Collaborator

Sorry for the late replay, I just saw hits and it probably would have been better put in the watch_it repository :-) I'm looking into it now

@escamoteur
Copy link
Collaborator

Fixed in 1.1.0 allready() now throw a correct time out exception and unless you provide an error handler it will also throw if you factory functions throw any other error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants