skip to Main Content

I’ve assigned a value for a local variable inside a function (Future), but the result always gives a null value. Is there any wrong code in my code?

enum StatusUser { telahMasuk, belumMasuk, berhasilMasuk, gagalMasuk }

class MyClass {
  Future<StatusUser> muatSeting(String? key) async {
    StatusUser? sp;

    final data = await getUserData();
    try {
      if (data != null) {
        final dataToken = jsonDecode(
            APIUser().decodeJWT(data['token'].toString().split('.')[1]));
        if (new DateTime.now().millisecondsSinceEpoch -
                dataToken['tgl_verify'] <
            864000) {
          sp = StatusUser.telahMasuk;
        }
      } else {
        sp = StatusUser.belumMasuk;
      }
    } catch (e) {
      print(e);
    }
    return sp!;
  }
}

When I debugging, its shows _CastError (Null check operator used on a null value). Whereas at previous version of Flutter, it works. I want that this future returning an enum value from variable sp.

❯ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.7, on Ubuntu 22.04.2 LTS 5.19.0-38-generic, locale id_ID.UTF-8)
Checking Android licenses is taking an unexpectedly long time...[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[!] Android Studio (not installed)
[✓] VS Code (version 1.76.2)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

3

Answers


  1. Chosen as BEST ANSWER

    I've solved it with adding else on nested if

    if (data != null) {
        final dataToken = jsonDecode(
            APIUser().decodeJWT(data['token'].toString().split('.')[1]));
        if (new DateTime.now().millisecondsSinceEpoch -
                dataToken['tgl_verify'] < 864000) {
            sp = StatusUser.telahMasuk;
        } else {
            sp = StatusUser.belumMasuk;
        }
      } else {
        sp = StatusUser.belumMasuk;
      }
    

    I'm in confuse with 'why nested if (child) when without else and false condition dosen't returning value that was set on else from parent if'


  2. The null check operator is failing here because sp is null.

    return sp!;
    

    Looking from the if statement, I think this condition fails (new DateTime.now().millisecondsSinceEpoch - dataToken['tgl_verify'] < 864000) and therefore sp is never set.

    if (data != null) {
        final dataToken = jsonDecode(
            APIUser().decodeJWT(data['token'].toString().split('.')[1]));
        if (new DateTime.now().millisecondsSinceEpoch -
                dataToken['tgl_verify'] <
            864000) { // this if statement never runs so sp is null.
          sp = StatusUser.telahMasuk;
        }
      }
    
    Login or Signup to reply.
  3. If you want StatusUser.belumMasuk to be returned by default, then you either should initialize sp to use that as its default value:

    Future<StatusUser> muatSeting(String? key) async {
      StatusUser sp = StatusUser.belumMasuk;
    
      final data = await getUserData();
      try {
        if (data != null) {
          final dataToken = jsonDecode(
              APIUser().decodeJWT(data['token'].toString().split('.')[1]));
          if (DateTime.now().millisecondsSinceEpoch - dataToken['tgl_verify'] <
              864000) {
            sp = StatusUser.telahMasuk;
          }
        }
      } catch (e) {
        print(e);
      }
      return sp;
    }
    

    or use the ?? operator:

    Future<StatusUser> muatSeting(String? key) async {
      StatusUser? sp;
    
      final data = await getUserData();
      try {
        if (data != null) {
          final dataToken = jsonDecode(
              APIUser().decodeJWT(data['token'].toString().split('.')[1]));
          if (DateTime.now().millisecondsSinceEpoch - dataToken['tgl_verify'] <
              864000) {
            sp = StatusUser.telahMasuk;
          }
        }
      } catch (e) {
        print(e);
      }
      return sp ?? StatusUser.belumMasuk;
    }
    

    Both cases would allow you to remove the else blocks and additionally would handle the case where an exception is thrown within the try block. (Incidentally, you should avoid catches without on clauses.)

    In your answer, you made a remark:

    I’m in confuse with ‘why nested if (child) when without else and false condition dosen’t returning value that was set on else from parent if

    Why would it? That’s not how ifelse works. The outer else block corresponds only to the outer if condition.

    Imagine:

    if (condition1) {
      if (condition2) {
        doStuff();
      }
    
      doLotsOfOtherStuff();
    } else {
      handleCondition1Failed();
    }
    

    If condition2 is false, do you expect doLotsOfOtherStuff() to be skipped? But if so, then doLotsOfOtherStuff() should be moved to be within the if (condition2) block. Do you expect doLotsOfOtherStuff() and handleCondition1Failed() to both be executed? Either of those choices would be unintuitive and very hard to follow for most people.

    If you want the else block to be executed if either condition1 or condition2 fails, then you should write it as:

    var succeeded = false;
    
    if (condition1) {
      if (condition2) {
        doStuff();
        succeeded = true;
      }
    
      doLotsOfOtherStuff();
    }
    
    if (!succeeded) {
      handleFailure();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search