一、前言
本系列文章旨在快速复习并上手Flutter开发,并在适当分享在项目实战过程中遇到的一些比较有价值的知识内容:
- 01-📝Flutter核心知识|了解Flutter【诞生背景、应用简介、页面渲染原理、搭建开发环境、创建Flutter项目的几种方式】
- 02-📝Flutter核心知识|Dart语言快速入门|常规语法【Dart介绍和安装、程序分析、常用数据类型、函数、运算符、逻辑分支】
- 03-📝Flutter核心知识|Dart语言快速入门|面向对象【类和对象、泛型、库的使用、异步模型、异步操作】
- 04-📝Flutter核心知识|了解Widget【Center、MaterialApp、Row、CheckBox、DIY、Column、ListView等】
- 05-📝Flutter核心知识|常用Widget1【StatefulWidget、文本Widget、按钮Widget、图片Widget、表单Widget】
- 06-📝Flutter核心知识|布局与滚动组件【单子布局、多子布局、JSON读取和解析、ListView、GridView、Slivers、监听滚动事件
- 07-📝Flutter核心知识|自定义Widget【StarRating、DashedLine、底部TabBar】
- 08-📝Flutter核心知识|网络请求和Json转Model【网络处理封装、Json转Model、Json解析 、自动反序列化配置等】
本系列文章内容篇幅如下:
- 一、了解Flutter开发
-
- Flutter的特性与应用场景
-
- Flutter绘制原理
-
- 与Flutter相关的技术原理
-
- 搭建Flutter开发环境
-
- 创建Flutter项目的几种方式
-
- 二、快速入门Flutter开发知识大纲
-
- Dart语言快速入门
-
- Flutter的Widget
-
- 三、常见应用功能模块与开源项目
-
- 常见应用功能模块
-
- 不错的开源项目
-
二、网络请求
Flutter 三方库 搜索地址: pub.dev/
1. 引入网络框架dio
- 在
pubspec.yaml
引入dio
框架,并 执行flutter pub get
:dependencies: dio: ^x.x.x #请使用pub上的最新版本
- 配置网络请求工具:
config.dart
class HttpConfig { static const String baseURL = "http://127.0.0.1:3000"; static const int connectTimeout = 5;// 请求超时时间 static const int receiveTimeout = 5;// 响应超时时间 } class HomeConfig { static const int movieCount = 20; }
http_request.dart
import 'package:dio/dio.dart'; import 'config.dart'; class HttpRequest { // 1. 请求配置 static final BaseOptions baseOptions = BaseOptions( baseUrl: HttpConfig.baseURL, connectTimeout: Duration(seconds: HttpConfig.connectTimeout), receiveTimeout: Duration(seconds: HttpConfig.receiveTimeout), ); static final dioNetworkRequest = Dio(baseOptions); // 2. 网络拦截器 static final InterceptorsWrapper dInter = InterceptorsWrapper( onRequest: (RequestOptions options, RequestInterceptorHandler handler) { // 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。 // 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。 print("path:${options.path}"); if (options.path == "/" ){ print("拦截了一个请求:${options.path}"); } return handler.next(options); }, onResponse: (Response response, ResponseInterceptorHandler handler) { // 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。 if (response.statusCode == "200" ){ print("拦截了一个请求:${response.statusCode}"); } // print(response.data); return handler.next(response); }, onError: (DioException error, ErrorInterceptorHandler handler) { // 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。 print(error); return handler.next(error); }); // 3. 基本网络请求 static Future<T> request<T>(String url, { String method = "get", Map<String, dynamic>? params, Interceptor? inter}) async { // 1.创建单独配置 final options = Options(method: method); // 全局拦截器 // 创建默认的全局拦截器 if (!dioNetworkRequest.interceptors.contains(dInter)){ List<Interceptor> inters = [dInter]; // 请求单独拦截器 if (inter != null) { inters.add(inter); } // 统一添加到拦截器中 dioNetworkRequest.interceptors.addAll(inters); } // 2.发送网络请求 try { Response response = await dioNetworkRequest.request(url, queryParameters: params, options: options); return response.data; } on DioError catch(e) { return Future.error(e); } } // 4. get请求 static Future<T> getRequest<T>(String url, { Map<String, dynamic>? params}) async { return HttpRequest.request(url,params: params); } // 5. post请求 static Future<T> postRequest<T>(String url, { Map<String, dynamic>? params}) async { return HttpRequest.request(url,method: "post",params: params); } }
- home模块的网络配置:
home_request.dart
import 'http_request.dart'; import '../models/home_models.dart'; import 'config.dart'; class HomeRequest { static Future<List<MovieItem>> requestMovieList(int start) async{ // 1.构建URL final movieURL = "/movie/top250?start=$start&count=${HomeConfig.movieCount}"; // 2.发送网络请求获取结果 final result = await HttpRequest.getRequest(movieURL); final subjects = result["subjects"]; // 3.将Map转成Model List<MovieItem> movies = []; for (var sub in subjects) { movies.add(MovieItem.fromJson(sub)); } return movies; } }
2. 配置网络处理工具
三、JSON解析
1. 加载Json文件/网络请求获取Json报文
- 网络请求获取Json报文 的 方式 在第二节 已说明
加载Json文件
- 在
pubspec.yaml
添加json文件的路径:(如下示例代码,assets: 部分)name: network_request description: "A new Flutter project." version: 1.0.0+1 environment: sdk: '>=3.3.1 <4.0.0' dependencies: flutter: sdk: flutter dio: ^5.4.1 json_annotation: ^4.8.0 cupertino_icons: ^1.0.6 dev_dependencies: build_runner: ^2.3.3 json_serializable: ^6.7.1 flutter_test: sdk: flutter flutter: uses-material-design: true assets: - assets/json/category.json #json文件路径 - assets/json/meal.json #json文件路径
- 执行
flutter pub get
引入资源文件
2. 加载JSON,JSON转Model
- 编写加载代码:
import 'dart:convert'; import 'package:flutter/services.dart'; import '../models/home_models.dart'; class JsonParse { static Future<List<CategoryModel>> getCategoryData() async { // 1.加载json文件 final jsonString = await rootBundle.loadString("assets/json/category.json"); // 2.将jsonString转成Map/List final result = json.decode(jsonString); // 3.将Map中的内容转成一个个对象 final resultList = result["category"]; List<CategoryModel> categories = []; for (var json in resultList) { categories.add(CategoryModel.fromJson(json)); } return categories; } }
四、自动反序列化配置
1. 在.yaml文件中引入以下依赖,在终端中运行 flutter pub get
命令获取依赖
dependencies:
flutter:
sdk: flutter
#使用JsonSerializable生成代码的必须要在需要生成代码的实体类前添加注解@JsonSerializable()
#使用这个注解我们必须引入json_annotation
json_annotation: ^4.0.0
dev_dependencies:
build_runner: ^2.0.0 #dart团队提供的一个生成dart代码文件的外部包
json_serializable: ^6.0.0 #json自动反序列化
2. 基本使用:
- 先创建Model类
- 再添加属性
- 给类添加默认的构造器:
- 引入头文件和要生成的模型文件的描述
- 头文件:
import 'package:json_annotation/json_annotation.dart';
- 要生成的模型文件的描述:
part 'xxx.g.dart';
- 注意:文件名,要小写
xxx
为当前文件的名字,例如:
- 头文件:
- 在这个类上添加
@JsonSerializable()
注解,并添加fromJson
和toJson
方法。- json转对象固定写法:
_${类名}FromJson(json)
- 对象转json固定写法:
_${类名}ToJson(json)
- json转对象固定写法:
- 在终端 执行 生成 模型文件指令:
flutter packages pub run build_runner build
import "package:json_annotation/json_annotation.dart";
part 'vip_open_record_model.g.dart';//注意,文件名,都要小写
@JsonSerializable() // 添加注解
class VipOpenRecordModel {
final int? orderId;
final String? orderSn;
final String? skuName;
final String? skuCode;
final int? memberType;
final String? startTime;
final String? endTime;
final String? payTime;
final num? price;
final String? payType;
final int? days;
// 默认的构造器:
VipOpenRecordModel({ this.orderId,
this.orderSn,
this.skuName,
this.skuCode,
this.memberType,
this.startTime,
this.endTime,
this.payTime,
this.price,
this.payType,
this.days,
});
factory VipOpenRecordModel.fromJson(Map<String, dynamic> json) => _$VipOpenRecordModelFromJson(json); // _${类名}FromJson(json) json转对象固定写法
Map<String, dynamic> toJson() => _$VipOpenRecordModelToJson(this); // _${类名}ToJson(json)对象转json固定写法 }
3. 自动生成反序列文件,控制台输入指令:
flutter packages pub run build_runner build
下面是自动生成的文件,注意:自动生成的内容不可以手动修改,如果需要增加字段,修改模型之后重新执行指令即可
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'vip_open_record_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
VipOpenRecordModel _$VipOpenRecordModelFromJson(Map<String, dynamic> json) =>
VipOpenRecordModel(
orderId: json['orderId'] as int?,
orderSn: json['orderSn'] as String?,
skuName: json['skuName'] as String?,
skuCode: json['skuCode'] as String?,
memberType: json['memberType'] as int?,
startTime: json['startTime'] as String?,
endTime: json['endTime'] as String?,
payTime: json['payTime'] as String?,
price: json['price'] as num?,
payType: json['payType'] as String?,
days: json['days'] as int?,
);
Map<String, dynamic> _$VipOpenRecordModelToJson(VipOpenRecordModel instance) =>
<String, dynamic>{
'orderId': instance.orderId,
'orderSn': instance.orderSn,
'skuName': instance.skuName,
'skuCode': instance.skuCode,
'memberType': instance.memberType,
'startTime': instance.startTime,
'endTime': instance.endTime,
'payTime': instance.payTime,
'price': instance.price,
'payType': instance.payType,
'days': instance.days,
};
4.然后就可以正常使用了:
List dataList = data;
for (var element in dataList) {
VipOpenRecordModel model = VipOpenRecordModel.fromJson(element);
openModelList.add(model);
}
使用自动反序列工具可以避免浪费时间在没有意义的工作上,同时也会避免因为书写失误造成的数据解析失败的问题,从而提高开发效率。