一、插件简介

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…

最后

如果你看到了这里,觉得文章写得不错就给个赞呗!欢迎大家评论讨论!如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足,定期免费分享技术干货。喜欢的小伙伴可以关注一下哦。谢谢!

更多相关文章

  1. 第三方QQ登录不回调 (Android)
  2. android 默认浏览器 无法下载,此手机不支持此内容(自定义文件or AP
  3. 使用InjectView和findViewById说拜拜
  4. Android(安卓)高手进阶教程(十三)之----Android(安卓)数据库SQLi
  5. Cordova插件编写流程(Android平台)
  6. Android之service一些基础回顾
  7. Android(安卓)网络连接:Volley(齐射)之简单使用
  8. 在Flutter启动Android的后台服务
  9. Android驱动程序开发和调试环境配置

随机推荐

  1. PHP递归函数删除所有子节点导致stackover
  2. PHP 使用 debug_print_backtrace() 或 de
  3. 在PHP中写入xml时,从字符串中删除&amp
  4. PHP-从多维数组中删除重复值
  5. php异常和错误处理
  6. 最好的PHP IDE和PHP文本编辑器合集
  7. php 顶部偶尔出现一个乱码字符?
  8. PHP如何获得地址栏的特殊字符呢?
  9. 使用PHP显示所有列条目
  10. ThinkPHP5.0框架开发--第10章 TP5.0验证