Flutter开始干系列-一个完整的登录实践
一、插件简介
connectivity
用于发现网络连接并进行相应配置。它可以区分蜂窝连接和WiFi连接,iOS和Android适用。
注意 在Android上,这不保证可以连接到Internet
shared_preferences
包装NSUserDefaults(在iOS上)和SharedPreferences(在Android上),为简单数据提供持久存储。
Dio
dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等。
二、依赖配置
在 pubspec.yaml 中添加插件依赖,下面插件版本是文章编写时的最新版。
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
三、登录操作
使用 Dio 构建登录请求
登录按钮的 onPressed 回调中,替换为 _doLogin() ,实现如下:
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); }
最后附上Github地址: github.com/joker-fu/fl…
最后
如果你看到了这里,觉得文章写得不错就给个赞呗!欢迎大家评论讨论!如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足,定期免费分享技术干货。喜欢的小伙伴可以关注一下哦。谢谢!
更多相关文章
- 第三方QQ登录不回调 (Android)
- android 默认浏览器 无法下载,此手机不支持此内容(自定义文件or AP
- 使用InjectView和findViewById说拜拜
- Android(安卓)高手进阶教程(十三)之----Android(安卓)数据库SQLi
- Cordova插件编写流程(Android平台)
- Android之service一些基础回顾
- Android(安卓)网络连接:Volley(齐射)之简单使用
- 在Flutter启动Android的后台服务
- Android驱动程序开发和调试环境配置