直接開始幹,沒有爲何~android
基於上一篇實現一個登錄頁,使用 connectivity 、 shared_preferences 、 Dio 實現一個完整的登陸操做,包含網絡鏈接檢測、請求、數據存儲等~git
固然,登陸接口並非我實現,是由玩Android友情提供。首先看效果:github
用於發現網絡鏈接並進行相應配置。它能夠區分蜂窩鏈接和WiFi鏈接,iOS和Android適用。json
注意 在Android上,這不保證能夠鏈接到Internet網絡
包裝NSUserDefaults(在iOS上)和SharedPreferences(在Android上),爲簡單數據提供持久存儲。app
dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等。async
在 pubspec.yaml 中添加插件依賴,下面插件版本是文章編寫時的最新版。ide
dependencies:
# https://github.com/flutterchina/dio
dio: ^3.0.3
# https://github.com/flutter/plugins/tree/master/packages/connectivity
connectivity: ^0.4.4
# https://github.com/flutter/plugins/tree/master/packages/shared_preferences
shared_preferences: ^0.5.3+4
複製代碼
今天的全部操做都基於上一篇實現一個登錄頁,有必要的能夠先跳轉過去查看。post
登陸按鈕的 onPressed 回調中,替換爲 _doLogin() ,實現以下:spa
Future _doLogin() async {
Dio dio = Dio();
dio.options..baseUrl = 'https://www.wanandroid.com/';
// 添加攔截器
dio.interceptors
..add(LogInterceptor(
requestHeader: true,
requestBody: true,
responseHeader: true,
responseBody: true,
));
// 發起請求
Response response = await dio.post('user/login',
data: FormData.fromMap({
"username": _accountController.text.trim(),
"password": _pwdController.text.trim(),
}));
if (response.statusCode == 200) {
UserEntity user = UserEntity.fromJson(response.data);
if (user.errorCode == 0) {
_showInfoDialog('登陸成功');
} else {
_showInfoDialog('登陸失敗:${user.errorMsg}');
}
} else {
_showInfoDialog('網絡請求異常:${response.statusMessage}');
}
}
複製代碼
點擊登陸,帳號密碼正確的狀況下,你將看到登陸成功!
在發起網絡請求前,咱們通常會檢測網絡,有網絡就發起,沒網絡就算逑... 須要注意這個庫在 Android 上還有個注意事項。
所在在 post 發起以前加上以下代碼,校驗網絡鏈接檢測:
// 檢測網絡鏈接
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
_showInfoDialog('網絡鏈接異常');
return;
}
複製代碼
通常登陸成功後,咱們會保存用戶信息,以便在後續操做使用到時方便獲取。
因此在確認真正登陸成功後,添加以下代碼保存用戶信息:
//登陸成功後 保存信息
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('user', jsonEncode(user.data));
複製代碼
connectivity 、shared_preferences 插件使用相對簡單,就再也不廢話了。到這一步若是網絡鏈接正常,且帳號密碼正確,將看到上面第一張圖示效果。不然:
登陸成功後,接下來須要在全部的請求中加上 token ,固然可能還有一些硬件信息什麼的。這裏經過添加 Dio 攔截器實現:
// 添加攔截器
dio.interceptors
..add(InterceptorsWrapper(
onRequest: (RequestOptions options) async {
var prefs = await SharedPreferences.getInstance();
var userJson = prefs.getString('user');
if (userJson != null && userJson.isNotEmpty) {
UserData user = UserData.fromJson(jsonDecode(userJson));
options.headers
..addAll({
'userId': user.id ?? '',
'token': user.token ?? '',
});
}
return options;
},
))
複製代碼
這樣網絡請求就會被攔截,添加 userId 和 token ...
通常進行網絡請求或者耗時操做時,會給用戶一個友好的提示,表示咱們沒有卡死。我這裏的處理是封裝了一個 LoadingDialog 的 Widget,使用 showDialog() 彈出,效果以下,具體實現請看代碼。
這個登陸實踐比較簡單,沒有對請求作統一的封裝,也沒有對異常進行處理。通常都是封裝後統一處理,調用的地方簡單不少。
最終 _doLogin 方法中的所有代碼,
Future _doLogin() async {
Dio dio = Dio();
dio.options..baseUrl = 'https://www.wanandroid.com/';
// 添加攔截器
dio.interceptors
..add(InterceptorsWrapper(
onRequest: (RequestOptions options) async {
var prefs = await SharedPreferences.getInstance();
var userJson = prefs.getString('user');
if (userJson != null && userJson.isNotEmpty) {
UserData user = UserData.fromJson(jsonDecode(userJson));
options.headers
..addAll({
'userId': user.id ?? '',
'token': user.token ?? '',
});
}
return options;
},
))
..add(LogInterceptor(
requestHeader: true,
requestBody: true,
responseHeader: true,
responseBody: true,
));
// 檢測網絡鏈接
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
_showInfoDialog('網絡鏈接異常');
return;
}
LoadingDialog.show(context);
// 發起請求
Response response = await dio.post('user/login',
data: FormData.fromMap({
"username": _accountController.text.trim(),
"password": _pwdController.text.trim(),
}));
if (response.statusCode == 200) {
UserEntity user = UserEntity.fromJson(response.data);
if (user.errorCode == 0) {
//登陸成功後 保存信息
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('user', jsonEncode(user.data));
_showInfoDialog('登陸成功');
} else {
_showInfoDialog('登陸失敗:${user.errorMsg}');
}
} else {
_showInfoDialog('網絡請求異常:${response.statusMessage}');
}
LoadingDialog.hide(context);
}
複製代碼