Flutter WillPopScope 与 AlertDialog 迁移到空安全

duf*_*ffy 8 flutter dart-null-safety

我最近将我的 Flutter 应用程序迁移到空安全,但 WillPopScope 与 AlertDialog 结合使用会导致问题。WillPopScope期望Future<bool>showDialog返回Future<bool?>,我不知道如何将一个投射到另一个上。

Widget _buildBody(BuildContext context) {
  return WillPopScope(
    onWillPop: (() => _onBackPressed(context)) as Future<bool> Function(),
    child: new Container([...]),
  );
}

// this should return a Future<bool> but showDialog doesn't allow that
Future<bool?> _onBackPressed(BuildContext context) async {
  if (someCondition) {
    // showDialog returns a Future<T?> 
    return showDialog(
      context: context,
      builder: (context) => new AlertDialog(
        [...]
        actions: <Widget>[
          new TextButton(
            child: Text("cancel",
            onPressed: () => Navigator.of(context).pop(false),
          ),
          new TextButton(
            child: Text("discard",
            onPressed: () => Navigator.of(context).pop(true),
          ),
        ],
    ));
  } else {
    return true;
  }
}
Run Code Online (Sandbox Code Playgroud)

本示例中所示的 onWillPop 中的转换(() => _onBackPressed(context)) as Future<bool> Function()不起作用。

The following _CastError was thrown building Builder(dirty):
type '() => Future<bool?>' is not a subtype of type '() => Future<bool>' in type cast
Run Code Online (Sandbox Code Playgroud)

知道如何捕获 showDialog 返回的 null 值并使 willPopScope 再次高兴吗?

Nut*_*uts 15

我想最简单的是:

Future<bool> _onBackPressed(BuildContext context) async {
    ...
    return (await showDialog(..)) ?? false // if dialog returns null, return false instead
    ...

Run Code Online (Sandbox Code Playgroud)

或者

bool? dialogResp = await showDialog(...);
if(dialogResp !=) 
   return dialogResp; 
else 
   return false;

Run Code Online (Sandbox Code Playgroud)

或者

Future<bool> _onBackPressed(BuildContext context) async {
    ...
    return showDialog(..).then((x) => x ?? false)
    ...
Run Code Online (Sandbox Code Playgroud)


Bak*_*ker 8

既然showDialog可以返回null,我们就可以在返回??时使用一个运算符来返回另一个值。在这种情况下,:showDialognullfalse

  Future<bool> _onWillPop() async {
    return (await showDialog(
      context: context,
      builder: (context) => new AlertDialog(),
    )) ?? false;
  }
Run Code Online (Sandbox Code Playgroud)

然后使用它WillPopScope

    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
Run Code Online (Sandbox Code Playgroud)