【问题标题】:Flutter display AlertDialog based on server responseFlutter 根据服务器响应显示 AlertDialog
【发布时间】:2020-12-24 18:49:26
【问题描述】:

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

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

基本算法是:

  • 发送请求。
  • 接收数据。 [如果数据好->真,如果坏->假]
  • 如果收到 true -> 移动到下一个屏幕。
  • 如果收到错误消息 -> 显示带有消息的警报对话框(密码用户名错误)

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

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

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

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

我将在下面发布代码。

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


    【解决方案1】:

    你需要做 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) 您的显示对话框不返回小部件。它会绘制一个弹出窗口,您可以在其中拥有小部件。所以,

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      • 2018-03-10
      • 1970-01-01
      • 2019-06-25
      相关资源
      最近更新 更多