網站首頁 編程語言 正文
其實dio框架已經封裝的很好了,但是在實戰項目中,為了項目可以統一管理,還是需要對dio框架進行二次封裝。
整體思路:一般情況下,后臺返回的數據我們可以分為兩部分
- 1.狀態數據
- 2.渲染數據
狀態數據就是接口有沒有正常返回數據相關的數據,這部分數據跟業務無關,我們可以封裝起來統一管理,渲染數據就是我們渲染頁面所需要的數據,這塊的數據需要我們自己處理。
接下來我們就主要處理渲染數據這塊的內容,我定義了兩個函數,渲染數據可能為一個對象或者一個數組,我做了分別處理,定義兩個函數來接受渲染數據。
// 定義兩個函數
typedef Success<T> = Function(T data); 請求數據data為obj對象
typedef SuccessList<T> = Function(List<T> data); // 請求數據data為[]數組
首先我們需要定義兩種數據接口的bean對象,返回對象示例:
/// 響應數據頭數據統一管理
class BaseRes<T> {
int? code;// 狀態碼
String? message; // 狀態碼說明
T? data; // 渲染數據
BaseRes({this.code, this.message, this.data});
factory BaseRes.fromJson(json) {
// json 渲染json數據
try {
if (json["code"] != null) {
try {
code = json["code"];
} catch (e) {
code = -1;
}
} else {
return BaseRes(code: -1, message: "服務器開小差了~", data: null);
}
return BaseRes(
code: json["code"] ?? -1,
message: json["message"],
data: BeanFactory.generateOBJ<T>(json["data"]));
} catch (e) {
return BaseRes(code: -1, message: "服務器開小差了~", data: null);
}
}
}
返回數組示例省略... 只把 T?data 改為 List<T?> data 即可,大同小異。
渲染實體類轉化:
/// 實體bean轉化工廠類
class BeanFactory {
static T? generateOBJ<T>(json) {
//T.toString() 類名
try {
switch (T.toString()) {
case "int":
return json;
case "bool":
return json;
case "String":
return json;
default:
// 實體類序列化
return TestBean.formJson(json) as T;
}
} catch (e) {
return null;
}
}
}
實體類:
/// 測試bean
class TestBean {
String? msg;
bool? isSelector;
TestBean(this.msg,this.isSelector);
TestBean.fromJson(dynamic json) {
msg = json["msg"];
isSelector = json["isSelector"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["msg"] = msg;
map["isSelector"] = isSelector;
return map;
}
}
實際項目中用的JsonToDart插件一鍵生成即可。(這個插件唯一不好的地方,不能在已生成的文件里序列化,其他都很好)。
接下來就需要進行對dio請求進行二次封裝,dio庫核心請求方法是request方法,dio的get、post方法都是基于request方法,所以我們要自己再次對request方法進行封裝成我們所需要的。
/// dio配置類
class DioManager {
static const baseUrl = "https://xxx"; // 正式環境
static DioManager instance = DioManager._internal();
Dio? _dio;
final Map<String, dynamic> _headers = {};
// 單例 私有化構造初始化dio
DioManager._internal() {
if (_dio == null) {
BaseOptions options = BaseOptions(
baseUrl: baseUrl,
contentType: Headers.jsonContentType,
responseType: ResponseType.json,
receiveDataWhenStatusError: false,
connectTimeout: _connectTimeout,
receiveTimeout: _receiveTimeout,
headers: _headers);
_dio = Dio(options);
/// 正式環境攔截日志打印
if (!const bool.fromEnvironment("dart.vm.product")) {
_dio?.interceptors
.add(LogInterceptor(requestBody: true, responseBody: true));
}
Future<Uint8List> imageToBytes(String imageUrl) async {
var response = await _dio?.get(imageUrl,
options: Options(responseType: ResponseType.bytes));
return Uint8List.fromList(response?.data);
}
get header => _headers;
/// 更新header
updateHeader() {
_dio?.options.headers = _headers;
}
/// 請求,返回的渲染數據 T
/// method:請求方法,NWMethod.GET等
/// path:請求地址
/// params:請求參數
/// success:請求成功回調
/// error:請求失敗回調
Future request<T>(Method method, String path,
{String? baseUrl,
Map<String, dynamic>? params,
data,
ProgressCallback? onSendProgress, // 上傳數據進度
ProgressCallback? onReceiveProgress, // 接受數據進度
Success<T>? success,
Function(ErrorRes)? error}) async {
try {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
if (error != null) {
error(ErrorRes(code: -9, message: "網絡異常~,請檢查您的網絡狀態!"));
}
return;
}
_setBaseUrl(baseUrl); // 動態設置baseUrl
Response? response = await _dio?.request(
path,
queryParameters: params,
data: data,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
options: Options(method: methodValues[method]),
);
if (response != null) {
BaseRes entity = BaseRes<T>.fromJson(response.data);
// 對象數據結構
if (entity.code == 200 && entity.data != null) {
if (success != null) success(entity.data);
} else {
if (error != null) {
error(ErrorRes(code: entity.code, message: entity.message));
}
}
} else {
if (error != null) error(ErrorRes(code: -1, message: "未知錯誤"));
}
} on DioError catch (e) {
if (error != null) error(createErrorEntity(e));
}
}
Http最終調用類:
typedef Success<T> = Function(T data); // 定義一個函數 請求成功回調
typedef Error = Function(ErrorRes errorRes); // 請求失敗統一回調
typedef SuccessList<T> = Function(List<T> data); // 請求數據data為[]集合
/// 通用調用接口類
class Http {
// 私有構造
Http._internal();
static Http instance = Http._internal();
/// get請求
/// baseUrl 切換baseUrl
/// params 參數
/// success 請求對象成功回調
/// successList 請求列表成功回調
/// error 錯誤回調
/// [isList] 請求的數據是否為List列表 默認對象
/// [isList]=true 請求data數據為[]list列表
void get<T>(String url,
{String? baseUrl,
Map<String, dynamic>? params,
Success<T>? success,
SuccessList<T>? successList,
Error? error,
bool isList = false}) {
if (isList) {
_requestList<T>(Method.get, url,
baseUrl: baseUrl, params: params, success: successList, error: error);
} else {
_request<T>(Method.get, url,
baseUrl: baseUrl, params: params, success: success, error: error);
}
}
/// post請求
/// baseUrl 切換baseUrl
/// params 參數
/// data 上傳表單數據 formData
/// success 請求對象成功回調
/// successList 請求列表成功回調
/// error 錯誤回調
/// [isList] 請求的數據是否為List列表 默認對象
/// [isList]=true 請求data數據為[]list列表
void post<T>(String url,
{String? baseUrl,
Map<String, dynamic>? params,
required data,
Success<T>? success,
SuccessList<T>? successList,
Error? error,
bool isList = false}) {
if (isList) {
_requestList<T>(Method.post, url,
data: data,
baseUrl: baseUrl,
params: params,
success: successList,
error: error);
} else {
_request<T>(Method.post, url,
data: data,
baseUrl: baseUrl,
params: params,
success: success,
error: error);
}
}
實戰應用調用:
我這邊對對業務模塊加了一層model處理,頁面只需要混入我們的model層調用具體的方法即可。
mixin LoginModel {
// get請求
loadCode(
String value, {
required Success<String> success,
required Error error,
}) {
Http.instance.get(Api.loadxxx,
params: {"key": value}, success: success, error: error);
}
}
可以看到,我們在頁面中只需要關注具體的業務請求就可以了。
原文鏈接:https://juejin.cn/post/7064487597661224973
相關推薦
- 2022-06-23 30行代碼實現React雙向綁定hook的示例代碼_React
- 2023-03-26 C#?cefSharep控件的使用詳情_C#教程
- 2022-07-04 python生成單位陣或對角陣的三種方式小結_python
- 2022-04-05 python中時間轉換錯誤:時間戳轉換|帶有時區的轉換 如何解析ISO 8601格式的日期?
- 2022-06-06 Python實現為PDF去除水印的示例代碼_python
- 2022-06-16 Kotlin對象比較注意點示例詳解_Android
- 2022-09-05 SpringBoot:整合JPA-Specifications動態查詢:
- 2022-11-20 TS?中的類型推斷與放寬實例詳解_其它
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支