简体   繁体   中英

Null check operator used on a null value on Flutter 2.5.3

i´m getting the error above on flutter version 2.5.3, and it is happening when i try to logout . Apparently the error has something to do with the Products provider, just like the error is showing. But i´m still not able to fix it. It may also have something to do with null safety, and since i´m not very acquainted to it, i might be missig something.

>         The following _CastError was thrown building _InheritedProviderScope<Products?>(dirty, dependencies: [_InheritedProviderScope<Auth?>], value: Instance of 'Products',
> listening to value):
>         Null check operator used on a null value

The relevant error-causing widget was ChangeNotifierProxyProvider<Auth, Products>

main.dart

return MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (context) => Auth()),
          ChangeNotifierProxyProvider<Auth, Products>(
            update: (context, auth, previousProducts) => Products(auth.token!, auth.userId,
                previousProducts == null ? [] : previousProducts.items),
            create: (_) => Products('', '', []),
          ),
          ChangeNotifierProvider(create: (context) => Cart()),
          ChangeNotifierProxyProvider<Auth, Orders>(
            update: (context, auth, previousOrders) => Orders(auth.token!,
                previousOrders == null ? [] : previousOrders.orders, auth.userId),
            create: (_) => Orders('', [], ''),
          ),
        ],
        child: Consumer<Auth>(
          builder: (context, authData, child) => MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              fontFamily: 'Lato',
              colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.purple)
                  .copyWith(secondary: Colors.deepOrange),
            ),
            home: authData.isAuth ? ProductsOverviewScreen() : AuthScreen(),
            //routes
          ),
        ));

auth.dart

class Auth with ChangeNotifier {
  String? _token;
  DateTime? _expiryDate;
  String? _userId;

  bool get isAuth {
    return token != null;
  }

  String get userId {
    return _userId!;
  }

  String? get token {
    if (_expiryDate != null &&
        _expiryDate!.isAfter(DateTime.now()) &&
        _token != null) {
      return _token;
    }
    return null;
  }

  Future<void> _authenticate(
      String email, String password, String urlSegment) async {
    final url = Uri.parse(
        "https://identitytoolkit.googleapis.com/v1/accounts:$urlSegment?key=AIzaSyAA9PShE7c2ogk5L13kI0mgw24HKqL72Vc");
    try {
      final response = await http.post(url,
          body: json.encode({
            'email': email,
            'password': password,
            'returnSecureToken': true
          }));
      final responseData = json.decode(response.body);
      if (responseData['error'] != null) {
        throw HttpException(responseData['error']['message']);
      }
      _token = responseData['idToken'];
      _userId = responseData['localId'];
      _expiryDate = DateTime.now()
          .add(Duration(seconds: int.parse(responseData['expiresIn'])));
    } catch (error) {
      throw error;
    }
    notifyListeners();
  }

  Future<void> logout() async {
    _token = null;
    _userId = null;
    _expiryDate = null;
    notifyListeners();
  }
}

Problem:

This issue was actually caused by the null check operator ( ! ) added to the non-nullable String variable auth.token in your main.dart file, which basically promises Dart that the value of auth.token would never be null, and that promise was not kept because the _token variable in the logout() method in your auth.dart file was set to null and your _token is actually passed to your token getter that you call using auth.token! in your main.dart file.

Solution:

You can of course easily fix this by removing the null check operator from the auth.token variable in your main.dart file and setting it to an empty String if it's value was equal to null, like this:

ChangeNotifierProxyProvider<Auth, Products>(
       create: (_) => Products('', '', []),
       update: (ctx, auth, previousProducts) => Products(
         auth.token ?? '',
         auth.userId ?? '',
         previousProducts == null ? [] : previousProducts.items,
       ),
     ),

you should also make your userId getter nullable like this or it would throw another error:

String? get userId {
  return _userId;
}

the ?? operator in Dart is basically an assignment operator that executes when the variable it is used for is equal to null.

And here's an extra guide from the Dart Team on working with null safety: https://dart.dev/null-safety

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM