首页 > 解决方案 > Flutter 根据服务器响应显示 AlertDialog

问题描述

我目前正在尝试制作登录屏幕。到目前为止,我能够通过遵循他们的文档自己解决问题。

但是,我想实现我目前无法做的某件事,并且不确定如何进行。

基本算法是:

我还没有学过导航,但是我在这里看到了一个文档页面。我正计划遵循那个。如果还有什么我需要知道的,请告诉我。

当谈到警报对话框时 - 我知道如何显示它,但是当我尝试这样做时,它给了我这个错误:

返回类型“Future”不是闭包上下文所要求的 Widget

我理解该消息,但由于我对颤动很陌生,我不确定在我的情况下显示带有自定义消息的警报对话框的正确方法是什么。请帮帮我。

我将在下面发布代码。

login_ui.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_first_flutter_app/remotedatasource/httpClient.dart';

class LoginForm extends StatefulWidget {
  @override
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final _loginFormKey = GlobalKey<FormState>();
  final _httpClient = new HttpClient();

  final usernameController = TextEditingController();
  final passwordController = TextEditingController();

  Future<bool> userSignIn;

  @override
  void dispose() {
    usernameController.dispose();
    passwordController.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
        key: _loginFormKey,
        child: Center(
            child: Container(
                    width: MediaQuery.of(context).size.width - 40,
                    height: 240,
                    margin: EdgeInsets.only(
                        left: 40, top: 40, right: 40, bottom: 40),
                    padding: EdgeInsets.only(
                        left: 15, top: 10, right: 15, bottom: 10),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(10),
                          topRight: Radius.circular(10),
                          bottomLeft: Radius.circular(10),
                          bottomRight: Radius.circular(10)),
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.5),
                          spreadRadius: 5,
                          blurRadius: 7,
                          offset: Offset(0, 3), // changes position of shadow
                        ),
                      ],
                    ),
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          TextFormField(
                            decoration: InputDecoration(
                                enabledBorder: OutlineInputBorder(
                                  borderSide: BorderSide(
                                    color: Colors.black,
                                  ),
                                  borderRadius: BorderRadius.circular(10.0),
                                ),
                                focusedBorder: OutlineInputBorder(
                                  borderSide: BorderSide(
                                    color: Colors.black,
                                  ),
                                  borderRadius: BorderRadius.circular(10.0),
                                ),
                                hintText: 'Username'),
                            validator: (value) {
                              if (value.isEmpty) {
                                return 'Field is empty';
                              } else {
                                return null;
                              }
                            },
                            controller: usernameController,
                          ),
                          TextFormField(
                            decoration: InputDecoration(
                                enabledBorder: OutlineInputBorder(
                                  borderSide: BorderSide(
                                    color: Colors.black,
                                  ),
                                  borderRadius: BorderRadius.circular(10.0),
                                ),
                                focusedBorder: OutlineInputBorder(
                                  borderSide: BorderSide(
                                    color: Colors.black,
                                  ),
                                  borderRadius: BorderRadius.circular(10.0),
                                ),
                                hintText: 'Password'),
                            validator: (value) {
                              if (value.isEmpty) {
                                return 'Field is empty';
                              } else {
                                return null;
                              }
                            },
                            controller: passwordController,
                            obscureText: true,
                            enableSuggestions: false,
                            autocorrect: false,
                          ),
                          SizedBox(
                              width: double.infinity,
                              height: 45,
                              child: ElevatedButton(
                                  onPressed: () {
                                    if (_loginFormKey.currentState.validate()) {
                                      setState(() {
                                        userSignIn = _httpClient.signIn(
                                            usernameController.text,
                                            passwordController.text);
                                      });
                                    }
                                  }, //TODO->Send login data
                                  child: Text(
                                    'Submit',
                                    textScaleFactor: 1.25,
                                  ))),
                          (userSignIn!=null)?FutureBuilder<bool>(
                            future: userSignIn,
                              builder: (context, snapshot) {
                                if(snapshot.hasData) {
                                  return showDialog(
                                      context: context,
                                      builder: (context) {
                                        return AlertDialog(
                                          content: Text(
                                              'Your data: \n username = ${usernameController.text} \n password = ${passwordController.text}'),
                                        );
                                      });
                                } else {
                                  return Text('Failure');
                                }
                              }
                          ) : null
                        ]
                    ))
                ));
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:my_first_flutter_app/loginscreen/ui/login_ui.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () {
          FocusScopeNode currentFocus = FocusScope.of(context);
          if (!currentFocus.hasPrimaryFocus &&
              currentFocus.focusedChild != null) {
            currentFocus.focusedChild.unfocus();
          }
        },
        child: MaterialApp(
          title: 'Login',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            body: LoginForm(),
          ),
        ));
  }
}

httpClient.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:my_first_flutter_app/util/util.dart';

class HttpClient {
  final String _loginURL = 'https://myurl/api/signin.api.php';

  Future<bool> signIn(String username, String password) async {
    final body = jsonEncode(<String, String>{
      'username': username,
      'password': password,
      'qpalzm': getAccessKey()
    });

    final response = await http.post(_loginURL,
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: body);

    if (response.statusCode == 200) {
      print(response.body);
      return true;
    } else if (response.statusCode == 401) {
      return false;
    } else {
      throw Exception('An unknown error occurred');
    }
  }
}

标签: flutter

解决方案


你需要做2-3件事:

(1) 而不是 Future 将变量设置为仅 bool

  bool userSignIn;

(2) 等待您的请求。所以而不是

onPressed: () {
                                    if (_loginFormKey.currentState.validate()) {
                                      setState(() {
                                        userSignIn = _httpClient.signIn(
                                            usernameController.text,
                                            passwordController.text);
                                      });
                                    }
                                  },

利用

onPressed: () async { //Use Async here
                                    if (_loginFormKey.currentState.validate()) {
                                      setState(() {
                                        userSignIn = await _httpClient.signIn( //await here
                                            usernameController.text,
                                            passwordController.text);
                                      });
                                    }
                                  },

(3) 你的show Dialog 没有返回Widget。它会绘制一个弹出窗口,您可以在其中拥有小部件。所以,

showDialog(
                                          context: context,
                                          builder: (context) {
return userSignIn ? LoginSuccessWidget() : LoginFailureWidget(); //Build what you want to show when login succeeds or fails, which could be AlertDialogs or Simple dialog or any other
           });

推荐阅读