08-Flutter中心常识|网络恳求和Json转Model【网络处理封装、Json转Model、Json解析 、主动反序列化装备等】

一、前语

本系列文章旨在快速温习并上手Flutter开发,并在适当分享在项目实战过程中遇到的一些比较有价值的常识内容:

本系列文章内容篇幅如下:

  • 一、了解Flutter开发
      1. Flutter的特性与运用场景
      1. Flutter绘制原理
      1. 与Flutter相关的技能原理
      1. 建立Flutter开发环境
      1. 创立Flutter项目的几种方法
  • 二、快速入门Flutter开发常识纲要
      1. Dart言语快速入门
      1. Flutter的Widget
  • 三、常见运用功能模块与开源项目
      1. 常见运用功能模块
      1. 不错的开源项目

二、网络恳求

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为当前文件的名字,例如:
        • 08-Flutter中心常识|网络恳求和Json转Model【网络处理封装、Json转Model、Json解析 、主动反序列化装备等】
  • 在这个类上添加@JsonSerializable()注解,并添加fromJsontoJson方法。
    • json转目标固定写法:_${类名}FromJson(json)
    • 目标转json固定写法:_${类名}ToJson(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);
}

运用主动反序列东西能够防止浪费时刻在没有意义的工作上,一起也会防止由于书写失误形成的数据解析失利的问题,然后进步开发功率。