flutter future局部变量不保存值并返回null

wi3ka0sx  于 2023-04-07  发布在  Flutter
关注(0)|答案(3)|浏览(101)

我在一个函数中为一个局部变量赋值(Future),但结果总是给出一个null值。我的代码中是否有错误的代码?

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!;
  }
}

当我调试时,它显示_CastError (Null check operator used on a null value)。而在以前的Flutter版本中,它可以工作。我希望这个future从变量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
k5ifujac

k5ifujac1#

这里的null检查操作符失败,因为sp为null。

return sp!;

从if语句来看,我认为这个条件失败了(new DateTime.now().millisecondsSinceEpoch - dataToken['tgl_verify'] < 864000),因此sp永远不会被设置。

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;
    }
  }
tzdcorbm

tzdcorbm2#

我通过在嵌套的if上添加else解决了这个问题

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;
  }

我对“为什么嵌套 if(child)当没有 else 和false条件时不返回从父 if 设置在 else 上的值”感到困惑。

z8dt9xmd

z8dt9xmd3#

如果你希望默认返回StatusUser.belumMasuk,那么你应该初始化sp以使用它作为默认值:

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;
}

或者使用??运算符:

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;
}

这两种情况都允许您删除else块,并且还可以处理在try块中抛出异常的情况(顺便说一句,您应该避免使用没有on子句的catch es)。
your answer中,您做了一个注解:
我对“为什么嵌套 if(child)当没有 else 和false条件时不返回从父 if 设置在 else 上的值”感到困惑。
为什么会这样?if-else不是这样工作的。外部的else块只对应于外部的if条件。
想象一下:

if (condition1) {
  if (condition2) {
    doStuff();
  }

  doLotsOfOtherStuff();
} else {
  handleCondition1Failed();
}

如果condition2false,你希望doLotsOfOtherStuff()被跳过吗?但是如果是这样,那么doLotsOfOtherStuff()应该被移动到if (condition2)块中。你希望doLotsOfOtherStuff() * 和 * handleCondition1Failed()都被执行吗?这两种选择对大多数人来说都是不直观的,很难理解。
如果你想在condition1condition2失败的情况下执行else块,那么你应该这样写:

var succeeded = false;

if (condition1) {
  if (condition2) {
    doStuff();
    succeeded = true;
  }

  doLotsOfOtherStuff();
}

if (!succeeded) {
  handleFailure();
}

相关问题