Flutter网络请求插件flutter_nb_net的使用
Flutter网络请求插件flutter_nb_net的使用
可能是 Flutter 上最强的网络框架, 基于dio实现的非侵入式框架(不影响原有功能). 学习成本低、使用简单, 一行代码发起网络请求, 甚至无需初始化。
功能特性
- RESTful API 设计
- GET/POST/PUT/HEAD/DELETE/PATCH/DOWNLOAD
- 可取消请求
- 异步解析,数据量大不再卡顿
- 全局错误处理(减少崩溃率)
- 自定义解析器,支持全局和单个请求
- 自定义解析方法
- 配置请求参数
- 漂亮的日志打印
- 证书快速配置
- 代理配置
- 拦截器配置
- 强制缓存模式/自定义缓存Key/缓存有效期/LRU缓存算法/缓存任何数据
- 监听上传/下载进度
开始使用
在 pubspec.yaml
文件中添加依赖:
dependencies:
flutter_nb_net: ^1.0.3
使用示例
全局配置
NetOptions.instance
// 添加头信息
.addHeaders({"aaa": '111'})
// 设置基础URL
.setBaseUrl("https://www.wanandroid.com/")
// 设置代理/HTTPS
.setHttpClientAdapter(IOHttpClientAdapter()
..onHttpClientCreate = (client) {
client.findProxy = (uri) {
return 'PROXY 192.168.20.43:8888';
};
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
return client;
})
// 添加 Cookie 管理器
.addInterceptor(CookieManager(CookieJar()))
// 添加缓存管理器
.addInterceptor(DioCacheManager(CacheConfig(
baseUrl: "https://www.wanandroid.com/",
)).interceptor)
// 添加缓存拦截器
.addInterceptor(DioCacheInterceptor(
options: CacheOptions(
store: MemCacheStore(),
policy: CachePolicy.forceCache,
hitCacheOnErrorExcept: [401, 403],
maxStale: const Duration(days: 7),
priority: CachePriority.normal,
cipher: null,
keyBuilder: CacheOptions.defaultCacheKeyBuilder,
allowPostMethod: false,
)))
// 设置全局解析器
.setHttpDecoder(MyHttpDecoder.getInstance())
// 设置超时时间
.setConnectTimeout(const Duration(milliseconds: 3000))
// 允许打印log,默认为 true
.enableLogger(true)
.create();
发起请求
获取原始数据
var appResponse = await get("banner/json");
appResponse.when(success: (dynamic) {
// var size = model.data?.length;
debugPrint("成功返回$dynamic");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
获取带泛型的数据
var appResponse = await get("banner/json", decodeType: BannerModel());
appResponse.when(success: (BannerModel model) {
var size = model.data?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
获取完整泛型的数据
var appResponse = await get<BannerModel, BannerModel>("banner/json",
decodeType: BannerModel());
appResponse.when(success: (BannerModel model) {
var size = model.data?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
发起 POST 请求
var appResponse = await post<UserWrapperModel, UserWrapperModel>(
"user/login",
decodeType: UserWrapperModel(),
queryParameters: {"username": '你的账号', "password": '你的密码'});
appResponse.when(success: (UserWrapperModel model) {
var nickname = model.data?.nickname;
debugPrint("成功返回nickname=$nickname");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
发起包含文件上传的 POST 请求
var path = '/Users/apple/Library/Developer/CoreSimulator/Devices/89F6C1CC-378B-48B3-9B8F-BA43E7870781/data/Containers/Data/Application/05B810A0-7552-4C3A-8080-800C06A15EC7/tmp/image_picker_289C3878-B39A-41AC-907F-18AE7A9DAE6E-8483-00001BCFA0738BBB.jpg';
var params = {'file': await MultipartFile.fromFile(path)};
var appResponse = await post<UserWrapperModel, UserWrapperModel>(
"v1/task/task/headPortrait",
options: Options(contentType: 'formData'),
decodeType: UserWrapperModel(),
data: params);
appResponse.when(success: (UserWrapperModel model) {
var nickname = model.data?.nickname;
debugPrint("成功返回nickname=$nickname");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
使用自定义解析器的 POST 请求
var appResponse = await post<UserModel, UserModel>("user/login",
decodeType: UserModel(),
httpDecode: MyHttpDecoder.getInstance(),
queryParameters: {"username": '', "password": ''});
appResponse.when(success: (UserModel model) {
var nickname = model.nickname;
debugPrint("成功返回nickname=$nickname");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
使用自定义解析器的 GET 请求
var appResponse = await get<BannerBean, List<BannerBean>>("banner/json",
decodeType: BannerBean(), httpDecode: MyHttpDecoder.getInstance());
appResponse.when(success: (List<BannerBean> model) {
var size = model.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:$msg");
});
自定保存和携带 cookie 的请求
var appResponse = await get<CollectModel, CollectModel>(
"lg/collect/list/0/json",
decodeType: CollectModel(),
httpDecode: MyHttpDecoder.getInstance());
appResponse.when(success: (CollectModel model) {
var size = model.datas?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:$msg");
});
带缓存的 GET 请求
var appResponse = await get<BannerModel, BannerModel>("banner/json",
options: buildCacheOptions(const Duration(days: 7)),
decodeType: BannerModel());
appResponse.when(success: (BannerModel model) {
var size = model.data?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
通过回调解析返回的请求
var appResponse = await get<BannerModel, List<BannerBean>>("banner/json",
options: buildCacheOptions(const Duration(days: 7)),
decodeType: BannerModel(), converter: (response) {
var errorCode = response.data['errorCode'];
/// 请求成功
if (errorCode == 0) {
var data = response.data['data'];
var dataList = List<BannerBean>.from(
data.map((item) => BannerBean.fromJson(item)).toList());
return Result.success(dataList);
} else {
var errorMsg = response.data['errorMsg'];
return Result.failure(msg: errorMsg, code: errorCode);
}
});
appResponse.when(success: (List<BannerBean> model) {
debugPrint("成功返回${model.length}条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
完整示例代码
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:dio_http_cache/dio_http_cache.dart';
import 'package:flutter/material.dart';
import 'package:flutter_nb_net/flutter_net.dart';
import 'model/banner_model.dart';
import 'model/collect_model.dart';
import 'model/user_model.dart';
import 'model/user_wrapper_model.dart';
import 'my_http_decoder.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
NetOptions.instance
// 添加头信息
.addHeaders({"aaa": '111'})
.setBaseUrl("https://www.wanandroid.com/")
// 设置代理/HTTPS
// .setHttpClientAdapter(IOHttpClientAdapter()
// ..onHttpClientCreate = (client) {
// client.findProxy = (uri) {
// return 'PROXY 192.168.20.43:8888';
// };
// client.badCertificateCallback =
// (X509Certificate cert, String host, int port) => true;
// return client;
// })
// 添加 Cookie 管理器
.addInterceptor(CookieManager(CookieJar()))
// 添加缓存管理器
// .addInterceptor(DioCacheManager(CacheConfig(
// baseUrl: "https://www.wanandroid.com/",
// )).interceptor)
// 添加缓存拦截器
.addInterceptor(DioCacheInterceptor(
options: CacheOptions(
store: MemCacheStore(),
policy: CachePolicy.forceCache,
hitCacheOnErrorExcept: [401, 403],
maxStale: const Duration(days: 7),
priority: CachePriority.normal,
cipher: null,
keyBuilder: CacheOptions.defaultCacheKeyBuilder,
allowPostMethod: false,
)))
// 设置全局解析器
// .setHttpDecoder(MyHttpDecoder.getInstance())
// 设置超时时间
.setConnectTimeout(const Duration(milliseconds: 3000))
// 允许打印log,默认为 true
.enableLogger(true)
.create();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
/// Get 请求原始数据
void requestGet() async {
var appResponse = await get("banner/json");
appResponse.when(success: (dynamic) {
debugPrint("成功返回$dynamic");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// Get 请求数据,不带泛型
void requestGet1() async {
var appResponse = await get("banner/json", decodeType: BannerModel());
appResponse.when(success: (BannerModel model) {
var size = model.data?.length;
debugPrint("不带泛型成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// Get 请求数据,完整的泛型
void requestGet2() async {
var appResponse = await get<BannerModel, BannerModel>("banner/json",
decodeType: BannerModel());
appResponse.when(success: (BannerModel model) {
var size = model.data?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// Post 请求
void requestPost() async {
var appResponse = await post<UserWrapperModel, UserWrapperModel>(
"user/login",
decodeType: UserWrapperModel(),
queryParameters: {"username": '你的账号', "password": '你的密码'});
appResponse.when(success: (UserWrapperModel model) {
var nickname = model.data?.nickname;
debugPrint("成功返回nickname=$nickname");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// Post 请求
void requestPostFile() async {
var path = '/Users/apple/Library/Developer/CoreSimulator/Devices/89F6C1CC-378B-48B3-9B8F-BA43E7870781/data/Containers/Data/Application/05B810A0-7552-4C3A-8080-800C06A15EC7/tmp/image_picker_289C3878-B39A-41AC-907F-18AE7A9DAE6E-8483-00001BCFA0738BBB.jpg';
var params = {'file': await MultipartFile.fromFile(path)};
var appResponse = await post<UserWrapperModel, UserWrapperModel>(
"v1/task/task/headPortrait",
options: Options(contentType: 'formData'),
decodeType: UserWrapperModel(),
data: params);
appResponse.when(success: (UserWrapperModel model) {
var nickname = model.data?.nickname;
debugPrint("成功返回nickname=$nickname");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// 自定义Decoder的 Post 请求
void requestCustomDecoderPost() async {
var appResponse = await post<UserModel, UserModel>("user/login",
decodeType: UserModel(),
httpDecode: MyHttpDecoder.getInstance(),
queryParameters: {"username": '', "password": ''});
appResponse.when(success: (UserModel model) {
var nickname = model.nickname;
debugPrint("成功返回nickname=$nickname");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// 自定义Decoder的 Get 请求
void requestCustomGet() async {
var appResponse = await get<BannerBean, List<BannerBean>>("banner/json",
decodeType: BannerBean(), httpDecode: MyHttpDecoder.getInstance());
appResponse.when(success: (List<BannerBean> model) {
var size = model.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:$msg");
});
}
/// 自定保存和携带 cookie 的请求
void requestCookieGet() async {
var appResponse = await get<CollectModel, CollectModel>(
"lg/collect/list/0/json",
decodeType: CollectModel(),
httpDecode: MyHttpDecoder.getInstance());
appResponse.when(success: (CollectModel model) {
var size = model.datas?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:$msg");
});
}
/// 带缓存的 Get 请求
void requestCacheGet() async {
var appResponse = await get<BannerModel, BannerModel>("banner/json",
options: buildCacheOptions(const Duration(days: 7)),
decodeType: BannerModel());
appResponse.when(success: (BannerModel model) {
var size = model.data?.length;
debugPrint("成功返回$size条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
/// 通过回调解析返回的请求
void requestCallBack() async {
var appResponse = await get<BannerModel, List<BannerBean>>("banner/json",
options: buildCacheOptions(const Duration(days: 7)),
decodeType: BannerModel(), converter: (response) {
var errorCode = response.data['errorCode'];
/// 请求成功
if (errorCode == 0) {
var data = response.data['data'];
var dataList = List<BannerBean>.from(
data.map((item) => BannerBean.fromJson(item)).toList());
return Result.success(dataList);
} else {
var errorMsg = response.data['errorMsg'];
return Result.failure(msg: errorMsg, code: errorCode);
}
});
appResponse.when(success: (List<BannerBean> model) {
debugPrint("成功返回${model.length}条");
}, failure: (String msg, int code) {
debugPrint("失败了:msg=$msg/code=$code");
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Dio'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () {
requestGet();
},
child: const Text('Get,原始数据'),
),
TextButton(
onPressed: () {
requestGet1();
},
child: const Text('Get 不带泛型'),
),
TextButton(
onPressed: () {
requestGet2();
},
child: const Text('Get 带泛型'),
),
TextButton(
onPressed: () {
requestPostFile();
},
child: const Text('上传图片'),
),
TextButton(
onPressed: () {
requestPost();
},
child: const Text('Post'),
),
TextButton(
onPressed: () {
requestCustomGet();
},
child: const Text('requestCustomGet'),
),
TextButton(
onPressed: () {
requestCustomDecoderPost();
},
child: const Text('requestCustomPost'),
),
const SizedBox(
height: 20,
),
const Text("请先打开34行注释,才能测试cookie"),
TextButton(
onPressed: () {
requestCookieGet();
},
child: const Text('requestCookieGet'),
),
const SizedBox(
height: 20,
),
const Text("请先打开39行注释,才能测试缓存"),
TextButton(
onPressed: () {
requestCacheGet();
},
child: const Text('requestCacheGet'),
),
TextButton(
onPressed: () {
requestCallBack();
},
child: const Text('requestCallBack'),
),
],
));
}
}
更多关于Flutter网络请求插件flutter_nb_net的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter网络请求插件flutter_nb_net的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 flutter_nb_net
插件进行网络请求的示例代码。flutter_nb_net
是一个 Flutter 插件,用于简化网络请求处理。下面是一个基本的示例,展示如何配置和使用它来进行 GET 和 POST 请求。
首先,确保你已经在 pubspec.yaml
文件中添加了 flutter_nb_net
依赖:
dependencies:
flutter:
sdk: flutter
flutter_nb_net: ^latest_version # 请替换为最新版本号
然后运行 flutter pub get
来安装依赖。
接下来,配置和使用 flutter_nb_net
插件进行网络请求。以下是一个完整的示例:
import 'package:flutter/material.dart';
import 'package:flutter_nb_net/flutter_nb_net.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Network Request Example'),
),
body: Center(
child: MyNetworkRequestWidget(),
),
),
);
}
}
class MyNetworkRequestWidget extends StatefulWidget {
@override
_MyNetworkRequestWidgetState createState() => _MyNetworkRequestWidgetState();
}
class _MyNetworkRequestWidgetState extends State<MyNetworkRequestWidget> {
final NetRequest _netRequest = NetRequest();
@override
void initState() {
super.initState();
// 配置网络请求
_netRequest.init(
baseUrl: 'https://api.example.com', // 替换为你的API基础URL
debugMode: true, // 是否开启调试模式
timeout: 10000, // 请求超时时间(毫秒)
);
// 发起GET请求示例
_netRequest.getRequest('path/to/your/endpoint', params: {'key': 'value'}).then((response) {
print('GET 请求响应: ${response.data}');
}).catchError((error) {
print('GET 请求错误: $error');
});
// 发起POST请求示例
var postData = {'key': 'value'};
_netRequest.postRequest('path/to/your/endpoint', data: postData).then((response) {
print('POST 请求响应: ${response.data}');
}).catchError((error) {
print('POST 请求错误: $error');
});
}
@override
Widget build(BuildContext context) {
return Text('网络请求已发送,请查看控制台输出');
}
}
// NetRequestResult 是请求结果的封装类,包含 data, statusCode, headers 等信息
class NetRequestResult {
final int statusCode;
final String? message;
final dynamic data;
final Map<String, List<String>>? headers;
NetRequestResult({
required this.statusCode,
this.message,
this.data,
this.headers,
});
@override
String toString() {
return 'NetRequestResult{statusCode: $statusCode, message: $message, data: $data, headers: $headers}';
}
}
注意事项
- 依赖版本:请确保将
flutter_nb_net: ^latest_version
替换为实际的最新版本号。 - API基础URL:将
baseUrl
替换为你的实际API基础URL。 - 请求路径:将
path/to/your/endpoint
替换为你的实际API路径。 - 调试模式:
debugMode
为true
时,插件会输出详细的请求和响应日志,便于调试。
结论
通过上述代码,你可以看到如何使用 flutter_nb_net
插件进行基本的 GET 和 POST 请求。该插件封装了底层的网络请求逻辑,使代码更加简洁和易于维护。