FutureBuilder 完全没有响应

FutureBuilder Completely Unresponsive

我的流程如下。屏幕只有两个元素 - TextFormField 和 ElevatedButton。

  1. 获取用户的电子邮件地址
  2. 用户点击按钮
  3. 按钮验证输入,然后
  4. 调用 FutureBuilder,
  5. 尝试从 REST 获取客户端记录API
  6. 重定向到适当的路线

这是我的第一个 Flutter/Dart 程序,仅供参考,所以我可能犯了初学者的错误。

问题:FutureBuilder 的第一行没有执行。没有错误,没有消息,什么都没有。为什么会这样?

用户输入邮箱地址,点击按钮,fetchClientInfo函数被执行,returns一个Future<ClientInfo>就这样。

你能帮忙吗?

@override
Widget build(BuildContext context) {
  final _formKey = GlobalKey<FormState>();

  return Scaffold(
      appBar: AppBar(
        title: Text("Register Profile"),
      ),
      body: Form(
          key: _formKey,
          child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Padding(
                    padding: EdgeInsets.all(20),
                    child: TextFormField(
                      controller: emailController,
                      validator: (email) {
                        if (email.isEmpty) {
                          return 'Please enter your email address.';
                        } else if (!EmailValidator.validate(email)) {
                          return 'Please enter a valid email address.';
                        }
                        return null;
                      },
                      decoration: InputDecoration(
                        border: new UnderlineInputBorder(borderSide: new BorderSide(color: Colors.red)),
                        labelText: 'Email',
                        hintText: 'Enter your email address',
                        contentPadding: EdgeInsets.all(20.0),
                      ),
                    )),
                ElevatedButton(
                    onPressed: () => {
                          if (_formKey.currentState.validate())
                            {
                              FutureBuilder<ClientInfo>(
                                future: fetchClientInfo(emailController.text),
                                builder: (BuildContext context, snapshot) {
                                  print("here");
                                  if (snapshot.data.outcome) {
                                    return Text("main screen");
                                  } else if (!snapshot.data.outcome) {
                                    Navigator.push(
                                        context,
                                        MaterialPageRoute(
                                            builder: (context) =>
                                                RegisterNewUser(emailAddress: emailController.text)));
                                  } else if (snapshot.hasError) {
                                    return Text("${snapshot.error}");
                                  }

                                  // Show a spinner
                                  return CircularProgressIndicator();
                                },
                              )
                            }
                        },
                    child: Text(
                      "Check Email",
                    ))
              ])));
}
Future<ClientInfo> fetchClientInfo(String emailAddress) async {
  var url = Uri.https(APIAccess.baseAPIURL, APIAccess.pathToClientAPI, {
    'client_id': '$emailAddress',
    'action': 'info',
    'key': '${APIAccess.key}'
  });

  final response = await http.get(url);

  if (response.statusCode == 200) {
    return ClientInfo.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to load album');
  }
}

您遗漏了几件事:

  1. return 语句(在您的 lambda 中您正在创建一个 FutureBuilder 但它没有在任何地方使用)
if(true) {
  return SizedBox.shrink();
}
  1. 正确的 lambda 语法(好吧,从技术上讲它是正确的,但它没有按照您的意愿进行):https://dart.dev/guides/language/language-tour#anonymous-functions
// that's how compiler sees it
Map<dynamic, dynamic> Function() foo = () => {
  
};

你所做的让我想起了 javascript,但在 dart 中 lambda 看起来有点不同

return Button(
  onTap: () => doStuff(),
);

return Button(
  onTap: () {
    doStuff();
  }
);

// and if you want to return a value from block lambda
return Builder(
  builder: (context) {
    return SizedBox.shrink();
  }
);
  1. 点击渲染小部件 处理点击事件时,最好将调用重定向到处理业务逻辑的组件,并且只监听小部件中的当前状态。

你想看的是状态管理。该主题自以为是,因此您必须自己选择适合您的解决方案。 https://flutter.dev/docs/development/data-and-backend/state-mgmt

我自己喜欢使用稍微修改过的 bloc 版本。您可以在此处找到 'original':https://pub.dev/packages/flutter_bloc

如果涉及到状态管理,一个新的事实上的标准是 Riverpod

如果您只是想让您的代码正常工作,请执行以下操作:

class Demo extends StatefulWidget {
  @override
  _DemoState createState() => _DemoState();
}

class _DemoState extends State<Demo> {

  Future<ClientInfo?> clientInfo = Future.value(null);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            setState(() {
              clientInfo = fetchClientInfo(emailController.text);
            });
          },
          child: _buildButtonContent(),
        ),
        FutureBuilder<ClientInfo>(
          initialData: null,
          future: clientInfo,
          builder: (BuildContext context, snapshot) {
            if (snapshot.data == null) {
              return SizedBox.shrink();
            } else {
              return Text(snapshot.data.toString());
            }
          },
        )
      ],
    );
  }
}