在之前的文章Flutter学习(三):网络请求Dio模块使用 中,我简单的介绍了Dio模块的使用和封装,比较浅显,使用时有很多不足和重复,在本文中,我将对封装进行进一步的优化。
常用功能配置 设置网络请求的拦截器在日常开发中使用非常广泛,例如:添加统一认证Header,判断登录状态已跳转登录页 简单实现:
1.创建Dio对象 推荐在一个工具文件中定义和初始化Dio对象,同时还可以定制Get、Post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import 'package:flutter/material.dart' ;import 'package:dio/dio.dart' ;import 'components/Dialog.dart' ;BaseOptions options = new BaseOptions( connectTimeout: 5000 , receiveTimeout: 10000 , responseType: ResponseType.plain ); Dio dio = new Dio(options); class Request { }
2.添加设置全局拦截器 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 import 'package:flutter/material.dart' ;import 'package:fluro/fluro.dart' ;import 'package:dio/dio.dart' ;import 'package:fluttertoast/fluttertoast.dart' ;import 'utils/request.dart' ;import 'utils/route.dart' ;void main() { final router = new Router(); Routes.configureRoutes(router); Routes.router = router; dio.interceptors.add(InterceptorsWrapper( onRequest: (RequestOptions options) async { print ('请求地址:' + options.uri.toString()); const token = '' ; if (token == '' ) { Fluttertoast.showToast(msg: '请登录后使用' , backgroundColor: Colors.black54, fontSize: 14.0 ); return dio.reject(errMsg); } else { options.headers['Authorization' ] = 'Bearer ' + token; options.headers['token' ] = token; return options; } onResponse: (Response response) async { print (response.data.toString()); String tempRes = response.data.toString(); if (tempRes[0 ] == '[' ) { tempRes = '{"reslut":' + tempRes + '}' ; } Map <String , dynamic > result = json.decode(tempRes.toString()); response.data = result; return response; }, onError: (DioError e) { if (e.type == DioErrorType.CONNECT_TIMEOUT || e.type == DioErrorType.RECEIVE_TIMEOUT || e.type == DioErrorType.SEND_TIMEOUT) { Fluttertoast.showToast(msg: '网络请求超时,请检查网络后重试' , backgroundColor: Colors.black54, fontSize: 12.0 ); } if (e.type == DioErrorType.CANCEL) { Fluttertoast.showToast(msg: '用户取消请求' , backgroundColor: Colors.black54, fontSize: 12.0 ); } return e; } )); runApp(MyApp()); } class MyApp extends StatelessWidget { }
3.请求方法封装 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 ... class Request { static Future<Map <String , dynamic >> get (String url, BuildContext context,{ bool showLoading = true , bool closeLoading = true }) async { if (showLoading) { showDialog<Null >( context: context, builder: (_) => LoadingDialog() ); } Response res = await dio.get (url); if (closeLoading) { Navigator.pop(context); } if (res.statusCode != 200 ) { return {}; } return res.data; } }
4.使用示例 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 import 'utils/request.dart' ;... class xxxState extends State <xxx > { ... @override void initState() { super .initState(); WidgetsBinding.instance.addPostFrameCallback((_){ getInfo(); }); } getInfo () { String url = 'xxx' ; Map <String , dynamic > infoMap = await Request.get (url, context); } ... } ...
使用效果
在使用时,如果出现inheritFromWidgetOfExactType(_LocalizationsScope) or inheritFromElement() was called before VideoInfoState.initState() completed
报错, 如下图: 查看自己initState
中调用网络请求方法是否使用WidgetsBinding.instance.addPostFrameCallback((_){}
处理