flutter封装dio请求库,让我们做前端的同学可以轻松上手使用,仿照axios的使用封装
1024小神 2024-06-17 17:33:03 阅读 77
dio是一个非常强大的网络请求库,可以支持发送各种网络请求,就像axios一样灵活强大,但是官网没有做一个demo示例,所以前端同学使用起来还是有点费劲,所以就想在这里封装一下,方便前端同学使用。
官网地址:dio | Dart Package
我的flutter模板项目地址: GitHub - Sjj1024/flutter_windows: 使用flutter开发跨平台桌面软件的案例
添加依赖
在pubspec.yaml文件中添加所需要的第三方依赖库
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 get: ^4.6.6 dio: ^5.4.0
封装基础请求工具
在utils里面新建一个request.dart文件,专门用来做请求工具的,就像前端框架里面集成axios一样:统一初始化网络请求常见配置,实现请求拦截器、响应拦截器以及错误处理。
request.dart 代码:
import 'package:dio/dio.dart';/// 请求方法:枚举类型enum DioMethod { get, post, put, delete, patch, head,}// 创建请求类:封装dioclass Request { /// 单例模式 static Request? _instance; // 工厂函数:执行初始化 factory Request() => _instance ?? Request._internal(); // 获取实例对象时,如果有实例对象就返回,没有就初始化 static Request? get instance => _instance ?? Request._internal(); /// Dio实例 static Dio _dio = Dio(); /// 初始化 Request._internal() { // 初始化基本选项 BaseOptions options = BaseOptions( baseUrl: 'http://你的服务器地址', connectTimeout: const Duration(seconds: 5), receiveTimeout: const Duration(seconds: 5)); _instance = this; // 初始化dio _dio = Dio(options); // 添加拦截器 _dio.interceptors.add(InterceptorsWrapper( onRequest: _onRequest, onResponse: _onResponse, onError: _onError)); } /// 请求拦截器 void _onRequest(RequestOptions options, RequestInterceptorHandler handler) { // 对非open的接口的请求参数全部增加userId if (!options.path.contains("open")) { options.queryParameters["userId"] = "xxx"; } // 头部添加token // options.headers["token"] = "xxx"; // 更多业务需求 handler.next(options); // super.onRequest(options, handler); } /// 相应拦截器 void _onResponse( Response response, ResponseInterceptorHandler handler) async { // 请求成功是对数据做基本处理 if (response.statusCode == 200) { // 处理成功的响应 // print("响应结果: $response"); } else { // 处理异常结果 print("响应异常: $response"); } handler.next(response); } /// 错误处理: 网络错误等 void _onError(DioException error, ErrorInterceptorHandler handler) { handler.next(error); } /// 请求类:支持异步请求操作 Future<T> request<T>( String path, { DioMethod method = DioMethod.get, Map<String, dynamic>? params, dynamic data, CancelToken? cancelToken, Options? options, ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { const _methodValues = { DioMethod.get: 'get', DioMethod.post: 'post', DioMethod.put: 'put', DioMethod.delete: 'delete', DioMethod.patch: 'patch', DioMethod.head: 'head' }; // 默认配置选项 options ??= Options(method: _methodValues[method]); try { Response response; // 开始发送请求 response = await _dio.request(path, data: data, queryParameters: params, cancelToken: cancelToken, options: options, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress); return response.data; } on DioException catch (e) { print("发送请求异常: $e"); rethrow; } } /// 开启日志打印 /// 需要打印日志的接口在接口请求前 Request.instance?.openLog(); void openLog() { _dio.interceptors .add(LogInterceptor(responseHeader: false, responseBody: true)); }}
管理apis网络请求
然后创建一个apis文件夹,集成所有的apis网络请求,并在里面创建user.dart、goods.dart等文件,用于对不同的网络请求进行管理,这样就可以知道我们相关的网路请求放在哪里面。并且对返回的数据根据实际需求进行处理,如果数据的修改需要更新UI或者需要全局共享该数据
app.dart文件代码:
import '../utils/request.dart';// 创建一个关于user相关请求的对象class UserApi { /// 单例模式 static UserApi? _instance; // 工厂函数:初始化,默认会返回唯一的实例 factory UserApi() => _instance ?? UserApi._internal(); // 用户Api实例:当访问UserApi的时候,就相当于使用了get方法来获取实例对象,如果_instance存在就返回_instance,不存在就初始化 static UserApi? get instance => _instance ?? UserApi._internal(); /// 初始化 UserApi._internal() { // 初始化基本选项 } /// 获取权限列表 getUser() async { /// 开启日志打印 Request.instance?.openLog(); /// 发起网络接口请求 var result = await Request().request('get_user', method: DioMethod.get); // 返回数据 return result.data; } // 获取列表数据 getGoods() async { var result = await Request().request("/game/gamemgnt", method: DioMethod.post, data: {"taskuuid": "queryprod", "splist": "66"}); // 返回数据 // print("getDetail:$result"); return result; } // 获取列表数据 getDetail() async { var result = await Request().request("/game/gamemgnt", method: DioMethod.post, data: {"taskuuid": "queryprod", "splist": "66"}); // 返回数据 // print("getDetail:$result"); return result; }}// 导出全局使用这一个实例final userApi = UserApi();
在组件页面使用
然后就可以到组件页面导入userApi给组件页面上使用,发送相应的网络请求了:
页面组件导入并发送请求获取数据,然后渲染:
import 'package:flutter/material.dart';import 'package:flutter_windows/apis/app.dart';class Lists extends StatefulWidget { const Lists({super.key}); @override State<Lists> createState() => _ListsState();}class _ListsState extends State<Lists> { // 列表数据 List goods = []; @override void initState() { // TODO: implement initState super.initState(); // 获取商品列表 getGoods(); } // 获取列表 getGoods() async { var res = await userApi.getGoods(); var goodsData = res['response_data']['data']; setState(() { goods = goodsData; }); } // 动态列表组件 List<Widget> _getListData() { var tempList = goods.map((value) { return Container( decoration: BoxDecoration( border: Border.all( color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)), child: Column( children: <Widget>[ Image.network( value['skillurl'], width: 100, height: 200, ), const SizedBox(height: 12), Text( value['pordname'], textAlign: TextAlign.center, style: const TextStyle(fontSize: 20), ) ], ), ); }); // ('xxx','xxx') print("渲染的列表组件类型:${tempList.toList().runtimeType}"); return tempList.toList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("产品列表"), ), body: GridView.count( crossAxisSpacing: 10.0, //水平子 Widget 之间间距 mainAxisSpacing: 10.0, //垂直子 Widget 之间间距 padding: const EdgeInsets.all(2), crossAxisCount: 4, //一行的 Widget 数量 // childAspectRatio: 0.7, //宽度和高度的比例 children: goods.map((value) { return Container( decoration: BoxDecoration( border: Border.all( color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)), child: Column( children: <Widget>[ Image.network( value['skillurl'], width: 100, height: 200, ), const SizedBox(height: 12), Text( value['pordname'], textAlign: TextAlign.center, style: const TextStyle(fontSize: 20), ) ], ), ); }).toList(), ), ); }}
最后展示的效果:
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。