在 Flutter 中从API获得响应后,在文本按钮中添加加载程序

bcs8qyzn  于 2023-03-24  发布在  Flutter
关注(0)|答案(1)|浏览(76)

按下TextButton后,应加载,直到从API获得响应。
例如:我已经登录TextButton,然后按下按钮后CircularProgressIndicator将显示和停止时,收到的响应,并移动到下一页。
请帮我解决这个问题

import "dart:convert";
import 'package:http/http.dart' as http;
import 'register.dart';
import 'package:crypto/crypto.dart';

void main() => runApp(const MaterialApp(
      home: LoginScreen(),
    ));

class LoginScreen extends StatefulWidget {
  const LoginScreen({Key? key}) : super(key: key);

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  bool passwordVisible = false;
  late String email;
  late String password1;
  var md5password = "";
  late SharedPreferences prefs;

  @override
  void initState() {
    super.initState();
    initSharedPref();
    passwordVisible = true;
  }

  void initSharedPref() async {
    prefs = await SharedPreferences.getInstance();
  }

  String generateMd5(String input) {
    return md5.convert(utf8.encode(input)).toString();
  }

  GlobalKey<FormState> formKey = GlobalKey<FormState>();

  final emailController = TextEditingController();
  final passwordController = TextEditingController();

  @override
  void dispose() {
    super.dispose();
    //clean up the controller when widget is disposed.
    emailController.dispose();
    passwordController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double width = MediaQuery.of(context).size.width;
    return WillPopScope(
      onWillPop: () async {
        return false;
      },
      child: Scaffold(
        backgroundColor: Colors.white,
        body: SingleChildScrollView(
          child: Form(
            key: formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  height: height * 0.30,
                  width: double.infinity,
                  decoration: const BoxDecoration(color: Colors.white),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      Image.asset(
                        "assets/title.png",
                        width: 350.0,
                      ),
                      const SizedBox(
                        height: 30,
                      ),
                    ],
                  ),
                ),
                const SizedBox(
                  height: 50,
                ),
                const Center(
                  child: Text('Login',
                      style: TextStyle(
                          fontSize: 30.0,
                          fontWeight: FontWeight.bold,
                          color: Colors.black,
                      )),
                ),
                const SizedBox(height: 30),
                Center(
                  child: SizedBox(
                    height: height * 0.08,
                    width: width - 35,
                    child: TextFormField(
                      controller: emailController,
                      validator: (email) {
                        if (email == null || email.isEmpty) {
                          return "Please enter Email";
                        } else if (!email.contains("@") ||
                            !email.contains(".")) {
                          return "Please enter a valid email address";
                        } 
                        return null;
                      },
                      onChanged: (value) {
                        setState(() {
                          email = value;
                        });
                      },
                      decoration: const InputDecoration(
                        border: OutlineInputBorder(),
                        enabledBorder: OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.black)),
                        focusedBorder: OutlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFF006ff6)),
                        ),
                        prefixIcon: Icon(Icons.email, color: Color(0xFF006ff6)),
                        labelText: mail,
                        labelStyle:
                            TextStyle(color: Colors.grey, fontSize: 13.0),
                      ),
                    ),
                  ),
                ),
                const SizedBox(height: 30),
                Center(
                  child: SizedBox(
                    height: height * 0.08,
                    width: width - 35,
                    child: TextFormField(
                      controller: passwordController,
                      validator: (password) {
                        if (password == null || password.isEmpty) {
                          return "Please enter your password";
                        }
                        return null;
                      },
                      onChanged: (value) {
                        setState(() {
                          password1 = value;
                        });
                        md5password = generateMd5(password1);
                        print(md5password);
                      },
                      obscureText: passwordVisible,
                      obscuringCharacter: "*",
                      decoration: InputDecoration(
                        border: const OutlineInputBorder(),
                        enabledBorder: const OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.black)),
                        focusedBorder: const OutlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFF006ff6)),
                        ),
                        prefixIcon: const Icon(Icons.lock_open,
                            color: Color(0xFF006ff6)),
                        labelText: password,
                        labelStyle:
                            const TextStyle(color: Colors.grey, fontSize: 13.0),
                        suffixIcon: IconButton(
                          icon: Icon(passwordVisible
                              ? Icons.visibility
                              : Icons.visibility_off),
                          onPressed: () {
                            setState(() {
                              passwordVisible = !passwordVisible;
                            });
                          },
                        ),
                      ),
                    ),
                  ),
                ),
                Align(
                  alignment: Alignment.centerRight,
                  child: TextButton(
                    onPressed: () {
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => const ForgotPass()));
                    },
                    child: const Text(
                      "Forgot your Password ?",
                      style: TextStyle(
                          color: Colors.grey,
                          decoration: TextDecoration.underline),
                    ),
                  ),
                ),
                const SizedBox(height: 20),
                Center(
                  child: SizedBox(
                    height: height * 0.08,
                    width: width - 35,
                    child: TextButton(
                      onPressed: () async {
                        if (formKey.currentState!.validate()) {
                          print(email);
                          print(md5password);
                          loginUser();
                     
                      },
                      style: TextButton.styleFrom(
                          backgroundColor: Color(0xFF006ff6),
                          shadowColor: Colors.black,
                          elevation: 5,
                          shape: const RoundedRectangleBorder(
                              borderRadius:
                                  BorderRadius.all(Radius.circular(10)))),
                      child: const Text(
                        "SIGN IN",
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 20.0,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ),
                ),
                const SizedBox(
                  height: 20.0,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text(
                      "Don't have an account?",
                      style: TextStyle(color: Colors.grey),
                    ),
                    TextButton(
                        onPressed: () {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => const Register()));
                        },
                        child: const Text(
                          "Sign up",
                          style: TextStyle(color: Colors.black),
                        ))
                  ],
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
  void loginUser() async {
    if (emailController.text.isNotEmpty && passwordController.text.isNotEmpty) {
      var reqBody = {
        "email": emailController.text,
        "password": md5password = generateMd5(passwordController.text)
      };

      var response = await http.post(
          Uri.parse("https://testing.com/user/login"),
          headers: {"Content-Type": "application/json"},
          body: jsonEncode(reqBody));

      if (response.statusCode == 200) {
        var jsonResponse = jsonDecode(response.body);
        if (jsonResponse['success']) {
          var myToken = jsonResponse['data']['token'];
          prefs.setString('token', myToken);
          print(myToken);
          Navigator.push(context,
              MaterialPageRoute(
                  builder: (context) => Dashboard(token: myToken)));
        } else {
          print('Something went wrong');
        }
        print(response.statusCode);
      }
      else if (response.statusCode == 400) {
        const snackBar = SnackBar(
          content: Text('Incorrect Username or Password'),
          backgroundColor: Colors.red,
          elevation: 10,
          behavior: SnackBarBehavior.floating,
          margin: EdgeInsets.all(5),
        );
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }
      else if(response.statusCode == 500){
        const snackBar = SnackBar(
          content: Text('Server Error'),
          backgroundColor: Colors.red,
          elevation: 10,
          behavior: SnackBarBehavior.floating,
          margin: EdgeInsets.all(5),
        );
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      } else {
        const snackBar = SnackBar(
          content: Text('Something went wrong'),
          backgroundColor: Colors.red,
          elevation: 10,
          behavior: SnackBarBehavior.floating,
          margin: EdgeInsets.all(5),
        );
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }
    }
  }
}

这是我的示例代码。

ulydmbyx

ulydmbyx1#

FutureBuilder。基本实现:

FutureBuilder(
              future: , // <- your function that awaits api response, must be Future function
              builder: (context, snapshot) {
              switch(snapshot.connectionState) {
                
                case ConnectionState.none:
                  // return normal working button
                 
                case ConnectionState.waiting:
                  // probably nothing to do here
                case ConnectionState.active:
                  // lock button functionality, return button with progress indicator or just the indicator;
                case ConnectionState.done:
                  // if correct push next screen if not handle wrong behavior
              }
            }),

小部件将根据API连接进行更新,并在future函数完成后真实的更新接收到的新数据。

相关问题