Flutter & Dio 网络交互
前言
flutter做网络请求目前最火的就是Dio库了,那么如何使用该库呢,怎么进行一个通用的封装呢,封装技巧能复用嘛?请看下文:
一:安装dio库 (dio: ^4.0.4) 官方地址传送门:github.com/flutterchin…
flutter pub add dio
二:dio的基本使用
import 'package:dio/dio.dart';
// 这里使用的是网易云api,感谢开源感谢分享!官方地址传送门:
// https://binaryify.github.io/NeteaseCloudMusicApi/#/
void send() async {
final query = {'id': 186016, 'limit': 1};
try {
// 实例化Dio,传入参数做一个get请求
final result = await Dio().get(
'http://123.207.32.32:9001/comment/music',
queryParameters: query,
);
// 打印结果
print(result);
} catch (e) {
// 打印异常
print(e);
}
}
使用dio的步骤就是,实例化一个Dio,使用该实例做某些请求(也许会传入一些参数),那么问题来了,每个页面都要生成这样的一个实例嘛?或者说有方法可以更好的管理dio,答案是有的,各位看官请继续:
三:dio的基本封装
一般来说,主要是对请求的配置信息,和网络拦截器做一个通用的封装,这边采取的思路是使用一个类来保存dio的实例,然后全局都可以使用该实例进行网络请求
-
编写网络配置类
class NetworkConfig { static const String baseUrl = 'http://123.207.32.32:9001/'; static const int sendTimeout = 8000; static const int connectTimeout = 8000; static const int receiveTimeout = 8000; } -
编写接口工具类(保存常用的接口,好管理)
class EndPoint { static const String comment = 'comment/music'; } -
编写dio的拦截器
// 拦截器可以做很多事情,具体可以看一下官方文档 // 假如我们在请求的时候需要添加token,那么就可以在onRequest里面进行处理 class NetworkIntercept extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { // 这里的AppCache缓存类在我的上一篇文章里有讲,有需要可以查看 // 从缓存中添加token,这里只是举一个例子,也有其他方式添加token final String? token = AppCache.token; if (token != null) { options.headers['token'] = token; } super.onRequest(options, handler); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { super.onResponse(response, handler); } @override void onError(DioError err, ErrorInterceptorHandler handler) { super.onError(err, handler); } } -
编写保存dio的单例类,
import 'package:dio/dio.dart'; import 'package:flutter_network/cache/cache.dart'; import 'package:flutter_network/network/network_config.dart'; class Network { final Dio dio; Network._({required this.dio}); factory Network._create(Dio dio) => Network._(dio: dio); static Network? _client; static void init() { if (_client == null) { // 创建配置信息 final BaseOptions options = BaseOptions( baseUrl: NetworkConfig.baseUrl, sendTimeout: NetworkConfig.sendTimeout, connectTimeout: NetworkConfig.connectTimeout, receiveTimeout: NetworkConfig.receiveTimeout, ); // 创建dio实例,并且添加配置信息 final Dio dio = Dio(options); // 对dio添加上面的拦截器 dio.interceptors.add(NetworkIntercept()); // 创建network实例并保存 _client = Network._create(dio); } } // 对外返回处理过的dio实例 static Dio get instance => _client!.dio; } -
封装后需要在main函数里面进行一次初始化,代码如下:
import 'package:flutter/material.dart'; import 'package:flutter_network/cache/cache.dart'; import 'package:flutter_network/network/network.dart'; import 'package:flutter_network/view/home_page.dart'; Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化缓存单例类 // 这里的AppCache缓存类在我的上一篇文章里有讲,有需要可以查看 await AppCache.init(); // 初始化网络单例类 Network.init(); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), home: HomePage(), ); } } -
那么封装好后,我们应该如何使用呢?简单,上代码:
import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_network/network/end_point.dart'; import 'package:flutter_network/network/network.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { // 引用网络单例类里面封装好的dio final Dio dio = Network.instance; Future<void> send() async { final query = { 'id': 186016, 'limit': 1, }; try { final result = await dio.get( EndPoint.comment, queryParameters: query, ); print(result); } catch (e) { print(e); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Network'), centerTitle: true, ), body: Center( child: FloatingActionButton( onPressed: send, child: Text('点击'), ), ), ); } } -
至此,dio的简单封装教程就结束了,有啥不懂得可以在评论区留言,或者有更好的方法也可以一起分享,感谢看完的铁铁们!:) 封装的技巧都是通用的,活学活用才是王道!
-
完整demo地址:github.com/yjf-ll/flut…