1、问题的提出
Flutter在进行异步请求的时候,很多时候因为网络阻塞等问题,会导致我们的数据可能几秒后才能获取到,但这几秒时间内,我们的页面怎么展示???
2、问题的解决
2.1、服务端的编写
我们使用SpringBoot搭建一个简易的请求
可以看到,故意将线程阻塞了2秒,用于模拟网络请求拥堵情况。
package com.example.login.controller;
import com.example.login.entity.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@PostMapping("/login/{username}/{password}")
public User Login(@PathVariable("username")String username,@PathVariable("password")String password){
try {
//睡2秒
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("username = " + username + ", password = " + password);
if("qykhhr".equals(username) && "123456".equals(password)){
//如果用户名和密码正确,返回一个User对象
User user = new User(username, password);
return user;
}
//如果用户名和密码错误,返回null
return null;
}
}
2.2、客户端的编写
import 'dart:convert';
import 'package:async_wait_test/User.dart';
import 'package:async_wait_test/test.dart';
import 'package:async_wait_test/test/widget/loading.dart';
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String username = "";
String password = "";
User user;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("异步请求测试"),
),
body: Center(
child: Column(
children: [
TextField(
decoration: InputDecoration(
hintText: "请输入用户名",
hintMaxLines: 1,
labelText: "用户名",
),
onChanged: (value){
setState(() {
username = value;
print("usernmae = $username");
});
},
),
TextField(
decoration: InputDecoration(
hintText: "请输入密码",
hintMaxLines: 1,
labelText: "密码",
),
onChanged: (value){
setState(() {
password = value;
print("password = $password");
});
},
),
RaisedButton(
child: Text("登录"),
onPressed: () {
Navigator.of(context).push(
//跳转页面,传入数据
MaterialPageRoute(builder: (context)=>test(username,password))
);
})
],
),
)
);
}
}
test.dart
import 'dart:convert';
import 'package:async_wait_test/User.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class test extends StatefulWidget {
String username;
String password;
test(this.username,this.password);
@override
_testState createState() => _testState();
}
class _testState extends State<test> {
User user;
//initState : 初始化widget的时候调用,只会调用一次。
@override
void initState() {
// TODO: implement initState
super.initState();
_getUser();
}
_getUser() async{
var response = await http.post("http://192.168.63.1:8080/login/${widget.username}/${widget.password}");
if(response.statusCode == 200){
var body = response.body;
var decode = json.decode(body);
// user = User(decode['username'], decode['password']);
setState(() {
user = User(decode['username'], decode['password']);
});
}
}
//build : 初始化之后开始绘制界面,当setState触发的时候会再次被调用
@override
Widget build(BuildContext context) {
// print("user = ${widget.user.username}");
if(this.user == null){
return Scaffold(
appBar: AppBar(
title: Text("登录中"),
),
body: Center(
child: CircularProgressIndicator(),
// child: CupertinoActivityIndicator(),
),
);
}
print("user = ${this.user.username}");
print("user = ${this.user.password}");
return Scaffold(
appBar: AppBar(
title: Text("登录成功"),
),
body: Center(
child: Column(
children: [
Text("${this.user.username}"),
Text("${this.user.password}"),
]
),
),
);
}
}
先对user对象进行判断,由于网络阻塞,刚开始的user是空值,所以页面显示登录中,当setState被调用的时候,user已经被赋值了,并且重新加载build,由于user不为空所以显示数据。
3、出现问题
但是有一个问题,因为我们这是一个登录功能,如何判断用户登录失败呢???
我采用的方法是:
如果用户名和密码不对,就返回一个User("error","error")对象,它的用户名和密码都是error。
@PostMapping("/login/{username}/{password}")
public User Login(@PathVariable("username")String username,@PathVariable("password")String password){
try {
//睡2秒
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("username = " + username + ", password = " + password);
if("qykhhr".equals(username) && "123456".equals(password)){
//如果用户名和密码正确,返回一个User对象
User user = new User(username, password);
return user;
}
//如果用户名和密码错误,返回null
return new User("error","error");
}
在Flutter判断用户名和密码是否都是"error",如果是那就是登录失败,否则就是登录成功。
if(this.user == null){
return Scaffold(
appBar: AppBar(
title: Text("登录中"),
),
body: LoadingWidget()
);
}else if(this.user.password == "error" && this.user.username == "error"){
return Scaffold(
appBar: AppBar(
title: Text("登录失败"),
),
body: RaisedButton(
child: Text("登录失败/(ㄒoㄒ)/~~,点击返回"),
onPressed: (){
Navigator.of(context).pop();
},
),
);
}else{
print("user = ${this.user.username}");
print("user = ${this.user.password}");
return Scaffold(
appBar: AppBar(
title: Text("登录成功"),
),
body: Center(
child: Column(
children: [
Text("${this.user.username}"),
Text("${this.user.password}"),
]
),
),
);
}