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:

    dart 复制代码
    dependencies:
      dio: ^x.x.x #请使用pub上的最新版本
  • 配置网络请求工具:

    • config.dart

      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

      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

      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: 部分)

    dart 复制代码
    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

  • 编写加载代码:

    dart 复制代码
    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 命令获取依赖

dart 复制代码
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() 注解,并添加 fromJsontoJson 方法。
    • json转对象固定写法:_${类名}FromJson(json)
    • 对象转json固定写法:_${类名}ToJson(json)
  • 在终端 执行 生成 模型文件指令:flutter packages pub run build_runner build
dart 复制代码
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. 自动生成反序列文件,控制台输入指令:

dart 复制代码
flutter packages pub run build_runner build

下面是自动生成的文件,注意:自动生成的内容不可以手动修改,如果需要增加字段,修改模型之后重新执行指令即可

dart 复制代码
// 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.然后就可以正常使用了:

dart 复制代码
List dataList = data;

for (var element in dataList) {
    VipOpenRecordModel model = VipOpenRecordModel.fromJson(element);
    openModelList.add(model);
}

使用自动反序列工具可以避免浪费时间在没有意义的工作上,同时也会避免因为书写失误造成的数据解析失败的问题,从而提高开发效率。

相关推荐
江上清风山间明月1 天前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能2 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人2 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen2 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang2 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang2 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1232 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-2 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力3 天前
Flutter应用开发:对象存储管理图片
flutter