Flutter响应数据解析插件response_parser的使用
Flutter响应数据解析插件response_parser的使用
简介
Response Parser 是一个用于简化从服务器解析数据和错误响应的Flutter插件。它可以帮助你编写更简洁、更易于维护的网络请求处理代码。
特性
- 简化错误处理:自动处理不同类型的错误,并返回统一的错误对象。
- 类型安全:使用
Either
类型来表示成功或失败的结果。 - 灵活配置:可以通过自定义解析器来适应不同的API响应格式。
许可证与版本
入门
假设你希望编写如下的简洁函数:
Future<Either<ApiFailure, User>> fetchUser() async {
return parseApiResponse(
requestAction: () => dio.get('/user'),
mapper: User.fromJson,
);
}
而不是以下冗长的代码:
Future<Either<ApiFailure, User>> fetchUser() async {
final dio = Dio(BaseOptions(baseUrl: 'https://example.com'));
try {
final request = await dio.get('/user');
final data = request.data?['data'];
if (data == null) {
final error = request.data?['error'];
if (error != null) {
return left(ApiFailure.serverFailure(error['message']));
} else {
return left(ApiFailure.unknown());
}
} else {
return right(User.fromJson(data));
}
} catch (error, st) {
ApiFailure? apiFailure;
if (error is DioError) {
final responseFailure = error.response?.data;
if (responseFailure is Map<String, dynamic>) {
apiFailure = ApiFailure.serverFailure(responseFailure['message']);
} else {
apiFailure = ApiFailure.httpError(error.response?.statusCode);
}
}
return left(apiFailure ?? ApiFailure.unknown());
}
}
如果你也想编写这样的简洁代码,请继续阅读!
不知道什么是 Either
?
Either
是来自 fpdart 包 的一个类型。它用于返回要么是错误(左),要么是数据(右)。
使用方法
为了使用 response_parser
,你需要进行一些准备工作。假设你的服务器返回如下的响应:
{
"data": {
// 请求的数据
},
"error": {
// 服务器错误,需要解析并显示给用户
"message": "Something went wrong"
}
}
并且你的错误模型如下所示:
class ApiFailure {
factory ApiFailure.unknown() = _UnknownApiFailure;
factory ApiFailure.serverFailure(String errorMessage) = _ServerFailure;
factory ApiFailure.httpError(int? statusCode) = _HttpError;
}
你需要实现 dataExtractor
、failureParser
和 errorCatcher
,如下所示:
final _exampleResponseParser = ResponseParser<Response, ApiFailure>(
dataExtractor: (response) => response.data['data']!,
failureParser: (response) {
final error = response.data['error'];
if (error is Map<String, dynamic>) {
return ApiFailure.serverFailure(error['message']);
} else {
return null;
}
},
errorCatcher: (error, stackTrace) {
ApiFailure? apiFailure;
if (error is DioError) {
apiFailure = ApiFailure.httpError(error.response?.statusCode);
}
return apiFailure ?? ApiFailure.unknown();
},
);
然后创建顶级的 parseApiResponse
、parseListApiResponse
和 parseEmptyApiResponse
函数:
final parseApiResponse = _exampleResponseParser.parseApiResponse;
final parseListApiResponse = _exampleResponseParser.parseListApiResponse;
final parseEmptyApiResponse = _exampleResponseParser.parseEmptyApiResponse;
工作原理
下图展示了 parseApiResponse
方法的工作原理:
实际上,parseApiResponse
方法中的所有操作都包裹在一个 try-catch
块中,因此该方法是安全的,不会抛出任何异常。
另一种使用方式
除了创建顶级函数,你还可以创建一个继承自 ResponseParserBase
的类,并重写其方法:
class DefaultResponseParser extends ResponseParserBase<Response, ApiFailure> {
@override
Object extractData(Response response) => response.data['data']!;
@override
Failure? parseFailure(Response response) {
final error = response.data['error'];
if (error is Map<String, dynamic>) {
return ApiFailure.serverFailure(error['message']);
} else {
return null;
}
}
@override
Failure catchError(Object error, StackTrace stackTrace) {
ApiFailure? apiFailure;
if (error is DioError) {
apiFailure = ApiFailure.httpError(error.response?.statusCode);
}
return apiFailure ?? ApiFailure.unknown();
}
}
示例代码
以下是一个完整的示例代码,展示了如何使用 response_parser
插件:
import 'package:dio/dio.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:response_parser/response_parser.dart';
part 'example.freezed.dart';
part 'example.g.dart';
final _exampleResponseParser = ResponseParser<Response, ApiFailure>(
dataExtractor: (response) => response.data['data']!,
failureParser: (response) => _parseApiFailure(response.data),
errorCatcher: (error, stackTrace) {
ApiFailure? apiFailure;
if (error is DioError) {
final responseFailure = error.response?.data;
if (responseFailure is Map<String, dynamic>) {
apiFailure = _parseApiFailure(responseFailure);
} else {
apiFailure = ApiFailure.httpError(error.response?.statusCode);
}
}
return apiFailure ?? ApiFailure.unknown();
},
);
ApiFailure? _parseApiFailure(Map<String, dynamic> json) {
final error = json['error'];
if (error is Map<String, dynamic>) {
return ApiFailure.serverFailure(error['message']);
} else {
return null;
}
}
final parseApiResponse = _exampleResponseParser.parseApiResponse;
final parseListApiResponse = _exampleResponseParser.parseListApiResponse;
final parseEmptyApiResponse = _exampleResponseParser.parseEmptyApiResponse;
Future<void> main() async {
final dio = Dio(BaseOptions(baseUrl: 'https://example.com'));
final userResult = await parseApiResponse(
requestAction: () => dio.get('/user'),
mapper: User.fromJson,
);
userResult.fold(
(failure) => print('Error: ${failure.displayError}'),
(user) => print('User is loaded: $user'),
);
final usersResult = await parseListApiResponse(
requestAction: () => dio.get('/users'),
mapper: User.fromJson,
);
usersResult.fold(
(failure) => print('Error: ${failure.displayError}'),
(users) => print('Users are loaded: $users'),
);
final deleteUserResult = await parseEmptyApiResponse(
requestAction: () => dio.delete('/user'),
);
deleteUserResult.match<void>(
() => print('User is successfully deleted!'),
(failure) => print('Error: ${failure.displayError}'),
);
}
@JsonSerializable()
class User {
User(this.name);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
final String name;
}
@freezed
class ApiFailure with _$ApiFailure {
ApiFailure._();
factory ApiFailure.unknown() = _UnknownApiFailure;
factory ApiFailure.serverFailure(String errorMessage) = _ServerFailure;
factory ApiFailure.httpError(int? statusCode) = _HttpError;
String get displayError => when(
unknown: () => 'Unknown',
serverFailure: (errorMessage) => errorMessage,
httpError: (statusCode) => 'Http error with status code $statusCode',
);
}
以上就是 response_parser
插件的使用方法。希望对你有所帮助!如果有更多问题,可以查看示例代码或查阅官方文档。
更多关于Flutter响应数据解析插件response_parser的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter响应数据解析插件response_parser的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用response_parser
插件来解析响应数据的示例代码。response_parser
插件可以简化从HTTP响应中提取数据的过程,尤其是当响应数据为JSON格式时。
首先,确保你已经在pubspec.yaml
文件中添加了response_parser
依赖:
dependencies:
flutter:
sdk: flutter
response_parser: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来,下面是一个完整的示例,展示了如何使用response_parser
来解析HTTP响应数据。
示例代码
- 定义数据模型
假设你有一个简单的用户数据模型:
class User {
final String id;
final String name;
final String email;
User({required this.id, required this.name, required this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String,
);
}
}
- 使用
response_parser
解析响应
接下来,在你的Flutter应用中,你可以使用dio
库(response_parser
通常与dio
一起使用)来发起HTTP请求,并使用response_parser
来解析响应。
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:response_parser/response_parser.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
User? user;
@override
void initState() {
super.initState();
_fetchUserData();
}
Future<void> _fetchUserData() async {
final Dio dio = Dio();
final ResponseParser parser = ResponseParser<User>(
(data) => User.fromJson(data),
);
try {
final Response<dynamic> response = await dio.get(
'https://api.example.com/users/1', // 替换为实际的API端点
options: Options(
responseType: ResponseType.json,
),
);
final Result<User> result = parser.parse(response.data);
if (result.success) {
setState(() {
user = result.data;
});
} else {
// 处理解析错误
print('Error parsing response: ${result.message}');
}
} catch (e) {
// 处理网络或其他异常
print('Error fetching data: $e');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('User Data'),
),
body: Center(
child: user == null
? CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('ID: ${user!.id}'),
Text('Name: ${user!.name}'),
Text('Email: ${user!.email}'),
],
),
),
),
);
}
}
解释
- 数据模型:
User
类定义了用户数据的结构,并包含了一个从JSON数据构造User
对象的工厂方法。 - HTTP请求:使用
dio
库发起HTTP GET请求。 - 响应解析:使用
ResponseParser
来解析响应数据。ResponseParser
的泛型参数指定了要解析的数据类型(在本例中是User
),并且提供了一个函数来将JSON数据转换为User
对象。 - UI更新:如果解析成功,则更新UI以显示用户数据;如果解析失败,则打印错误信息。
这个示例展示了如何在Flutter应用中使用response_parser
插件来简化HTTP响应数据的解析过程。你可以根据实际需求调整代码,例如处理更复杂的响应结构或添加更多的错误处理逻辑。