以登录页面跳转为例,实现接口请求以及正在加载页面效果。

因为web大家都比较熟悉,就以最简单的方式简单描述一下。

flutter可能比较多的点是需要注意的。

web中的实现

界面的实现主要通过position来将正在加载页面显示在登录表单前面。代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.wrap-loading {
/* 遮盖整页,并添加背景色 */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(255, 255, 255, .5);

/* 居中 */
display: flex;
align-items: center;
justify-content: center;
}

逻辑主要是就显示加载页面-请求完成-隐藏加载页面。代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function toLogin () {
$('.wrap.loading').show()
$.ajax({
url: url,
success: function (data) {
$('.warp.loading').hide()
if (success) {
enterHome()
} else {
showError()
}
}
})
}

flutter中的实现

首先还是界面的实现。

实现正在加载页肯定是有许多种方式的,其中最佳的方式应该就是通过FutureBuilder(初学dart和flutter,组件是最佳实践,代码是个人目前的能力)。

FutureBuilder的官方文档在这里,简单来说的话,就是他可以通过Future的状态,显示不同的组件,主要用的构造属性也就是futurebuilder

考虑页面的状态,应该包括还未发送请求状态、请求已发送还未返回的状态、以及请求成功的状态。

FutureBuilder中的builder回调函数中,参数为contextAsyncSnapshot,其中AsyncSnapshot包含属性connectionState可以用于判断链接的当前状态。

代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// FutureBuilder中的future需要点击登录之后赋值,所以需要StatefulWidget

class LoginScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return LoginScreenState();
}
}

class LoginScreenState extends State<LoginScreen> {

Future<Response> _loginFuture;

_toHomeScreen (context) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => HomeScreen()
), (route) => false);
}

_fetchLogin (username, password) {
// 发送请求,调用setState,使得重新渲染
setState(() {
_loginFuture = http.post(
baseUrl + loginUrl,
body: {
username: username,
password: password
}
);
});
return _loginFuture;
}

// 返回加载,或什么也不显示
_showLoading (isShow) {
if (isShow) {
return Center(
child: FullScreenLoading(),
);
} else {
return Center();
}
}

@override
Widget build(BuildContext context) {
return FutureBuilder(
// _loginFuture状态改变,就会重新渲染
future: _loginFuture,
builder: (context, snapshot) {
print(snapshot.connectionState);
// Stack叠加组件,这里相当于上面web代码中position: absolute的作用
return Stack(
children: <Widget>[
Scaffold(
body: Container(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LoginForm(_fetchLogin, success: _toHomeScreen),
],
)
),
bottomNavigationBar: Container(
margin: const EdgeInsets.only(bottom: 20.0),
child: BottomLinksBar(),
)
),
// 根据状态不同,显示不同
_showLoading(snapshot.connectionState == ConnectionState.waiting)
],
);
},
);
}

}

在dart中,异步编程主要是在dart:async中,包括FutureStream等类,这次主要用到的是FutureFutrue是一个很类似于JavaScript中的Promise的存在。