当前位置: 首页 > news >正文

Flutter自定义model实体类

在某些场景下,我们可能需要自定义Flutter model实体类,来创建更加结构化和有组织的代码,提高代码的可重用性,并增强Flutter应用程序的整体可维护性。

  1. 自定义小部件:在创建自己的小部件时,可能需要定义自定义数据类型来封装小部件的特定数据和行为。

  2. API集成:在使用API时,您可能需要定义自定义数据类型,以便以结构化的方式解析和表示响应数据。这有助于更有效地处理和操作数据。

  3. 状态管理:在像Provider或Riverpod这样的状态管理解决方案中,你可以定义自定义数据类型来表示应用程序的状态,并相应地更新它。

  4. 表单验证:在构建表单时,您可能希望定义自定义数据类型来表示表单字段并对输入值执行验证。

一、认识Flutter的model

1、model类的结构

一般常用的会有以下几个

  • 1、【必须】属性

  • 2、【必须】构造方法

  • 3、【必须】fromJson: 序列化 -> model实体类

  • 4、【可省】toMap(toJson):model实体类 -> 序列化 (如果不需要序列化可以缺省)

上述中:toMap也可写成toJson。

实际上在Flutter中,约定是在将对象转换为json可序列化映射时更多地使用toJson()而不是toMap()。但是,只要方法的功能清楚,实际的方法名称并不重要。

import 'package:wechat/tools/convert_util.dart';class OrderDataEntity {//【必须】属性String? type;//【必须】构造方法OrderDataEntity({required this.type,});//【必须】Map转Modelfactory OrderDataEntity.fromJson(Map<String, dynamic> jsonRes) {return OrderDataEntity(// 这里根据情况选择是否可以为空,然后指定默认值type: asT<String>(jsonRes['type']),// type: asT<String>(jsonRes['type']) ?? '',);}//【可省】model转MapMap<String, dynamic> toJson() => {'type': type,};
}

除了常用的还有不常用的

  • 5、【可省】toString:这个重写的Object的方法

toString一般不需要重写,使用orderDataEntity.toJson().toString()替代即可

  • 6、【可省】copy:拷贝数据时可实现copy方法
//【可省】一般不需要重写,使用toJson.toString()替代

String toString() {return 'OrderDataEntity{name: $type}';
}//【可省】提供copy功能
OrderDataEntity copy() {return OrderDataEntity(type: type,);
}

2、可空类型处理

对于变量声明,如果是网络返回的建议声明为可空类型,如果是自定义组件使用建议声明为不可空类型。

  • 可空类型
String? type;
// 对应的构建model
type: asT<String>(jsonRes['type']),
  • 不可空类型
String type;
// 对应的构建model
type: asT<String>(jsonRes['type'])??'',

二、属性为基本数据

对于简单数据类型可以直接转换

  • 数字:num、int、double

  • 字符串:String

  • 布尔:bool

不同类型在使用上的区别

1、替换属性类型

2、替换fromJson中的泛型与默认值(不可空类型才需要默认值)

// 示例
String type;
num age;type: asT<String>(jsonRes['type']) ?? '',
age: asT<num>(jsonRes['age']) ?? 0,

三、属性为集合

1、集合List<String>

import 'package:wechat/tools/convert_util.dart';class OrderDataEntity {// 属性String? type;List<String>? orderList;// 构造方法OrderDataEntity({required this.type,required this.orderList,});// model转MapMap<String, dynamic> toJson() => {'type': type,'orderList': orderList,};// Map转Modelfactory OrderDataEntity.fromJson(Map<String, dynamic> jsonRes) {List<OrderDataOrderList> orderList = [];for (final dynamic item in (jsonRes['orderList'] ?? [])) {orderList.add(OrderDataOrderList.fromJson(asT<Map<String, dynamic>>(item)!));}return OrderDataEntity(type: asT<String>(jsonRes['type']) ?? '',orderList: asListT<String>(jsonRes['orderList']),);}
}

2、嵌套List<Map<String, dynamic>>

class OrderDataOrderList {List<Map<String, dynamic>>? saleGoodsAppearanceImagesList;OrderDataOrderList({required this.saleGoodsAppearanceImagesList,});Map<String, dynamic> toJson() => {'saleGoodsAppearanceImagesList': saleGoodsAppearanceImagesList,};factory OrderDataOrderList.fromJson(Map<String, dynamic> jsonRes) {List<Map<String, dynamic>>? saleGoodsAppearanceImagesList;if (jsonRes['saleGoodsAppearanceImagesList'] != null) {saleGoodsAppearanceImagesList = List<Map<String, dynamic>>.from(jsonRes['saleGoodsAppearanceImagesList'].map((item) {return Map<String, dynamic>.from(item);}).toList());}return OrderDataOrderList(saleGoodsAppearanceImagesList: saleGoodsAppearanceImagesList,);}
}

四、属性为model

1、model

这个相当于套娃,

1、在生成toJson时调用子model的toJson即可

2、在生成tfromJson时调用子model的fromJson即可

import 'package:wechat/tools/convert_util.dart';class OrderDataEntity {// 属性String? type;OrderDataOrderList? orderList;// 构造方法OrderDataEntity({required this.type,required this.orderList,});// model转MapMap<String, dynamic> toJson() => {'type': type,'orderList': orderList?.toJson(),};// Map转Modelfactory OrderDataEntity.fromJson(Map<String, dynamic> jsonRes) {return OrderDataEntity(type: asT<String>(jsonRes['type']) ?? '',orderList: OrderDataOrderList.fromJson(jsonRes['orderList']),);}
}class OrderDataOrderList {int? id;OrderDataOrderList({required this.id,});Map<String, dynamic> toJson() => {'id': id,};factory OrderDataOrderList.fromJson(Map<String, dynamic> jsonRes) {return OrderDataOrderList(id: asT<int>(jsonRes['id']),);}
}

2、嵌套List<Model>

// 方法1:使用工具asListT工具
factory OrderDataEntity.fromJson(Map<String, dynamic> jsonRes) {return OrderDataEntity(orderList: asListT<OrderDataOrderList>(jsonRes['orderList'],fromJson: (json) => OrderDataOrderList.fromJson(json)),);
}// 方法2:等价于自己遍历解析
factory OrderDataEntity.fromJson(Map<String, dynamic> jsonRes) {List<OrderDataOrderList> orderList = [];for (final dynamic item in (jsonRes['orderList'] ?? [])) {orderList.add(OrderDataOrderList.fromJson(asT<Map<String, dynamic>>(item)!));}return OrderDataEntity(orderList: orderList,);
}

完整示例

import 'package:wechat/tools/convert_util.dart';class OrderDataEntity {// 属性String? type;List<OrderDataOrderList>? orderList;// 构造方法OrderDataEntity({required this.type,required this.orderList,});// model转MapMap<String, dynamic> toJson() => {'type': type,'orderList': orderList?.map((item) => item.toJson()).toList(),};// Map转Modelfactory OrderDataEntity.fromJson(Map<String, dynamic> jsonRes) {return OrderDataEntity(type: asT<String>(jsonRes['type']) ?? '',orderList: asListT<OrderDataOrderList>(jsonRes['orderList'],fromJson: (json) => OrderDataOrderList.fromJson(json)),);}
}class OrderDataOrderList {int? id;OrderDataOrderList({required this.id,});Map<String, dynamic> toJson() => {'id': id,};factory OrderDataOrderList.fromJson(Map<String, dynamic> jsonRes) {return OrderDataOrderList(id: asT<int>(jsonRes['id']),);}
}

五、工具类convert_util.dart

import 'dart:convert';import 'package:flutter/foundation.dart';void tryCatch(Function? f) {try {f?.call();} catch (e, _) {debugPrint('$e');}
}class FFConvert {FFConvert._();static T? convert<T extends Object?>(dynamic value) {if (value == null) {return null;}return json.decode(value.toString()) as T?;}
}T? asT<T extends Object?>(dynamic value, [T? defaultValue]) {if (value is T) {return value;}try {if (value != null) {final String valueS = value.toString();if ('' is T) {return valueS as T;} else if (0 is T) {return int.parse(valueS) as T;} else if (0.0 is T) {return double.parse(valueS) as T;} else if (false is T) {if (valueS == '0' || valueS == '1') {return (valueS == '1') as T;}return (valueS == 'true') as T;} else {return FFConvert.convert<T>(value);}}} catch (e, _) {debugPrint('asT<$T>,error: $e');return defaultValue;}return defaultValue;
}List<T>? asListT<T extends Object?>(dynamic value, {T Function(Map<String, dynamic> json)? fromJson,bool allowDirty = false,
}) {if (value is! List) return null;return value.fold<List<T>>([], (list, element) {try {if (element == null) {return list;} else {final _parsedValue = fromJson != null ? fromJson(element) : asT<T>(element);if (_parsedValue == null && !allowDirty) {throw Exception('asListT Parse Error: data: ${jsonEncode(element)}');}if (_parsedValue != null) list.add(_parsedValue);}} catch (_) {debugPrint('dirty data found: ${jsonEncode(element)}');if (!allowDirty) {rethrow;}}return list;});
}

六、额外数据解析

1、List<Map> -> List<String>

List<Map<String, dynamic>>中抽离List<String>

List<String> orderIdList = goodsList.map((e) => e.orderId ?? "").toList();

2、Map转json字符串

import 'dart:convert';Map<String, dynamic> myMap = {'key1': 'value1', 'key2': 2};String jsonString = json.encode(myMap);print(jsonString); // {"key1":"value1","key2":2}

3、json字符串转Map

import 'dart:convert';String jsonString = '{"key1":"value1","key2":2}';Map<String, dynamic> myMap = json.decode(jsonString);print(myMap); // {key1: value1, key2: 2}

4、List<dynamic>List<Map<String,dynamic>>

List<dynamic> myList = [{'key1': 'value1', 'key2': 2}, {'key1': 'value2', 'key2': 3}];List<Map<String, dynamic>> myNewList = myList.map((item) => Map<String, dynamic>.from(item)).toList();print(myNewList); // [{key1: value1, key2: 2}, {key1: value2, key2: 3}]

相关文章:

Flutter自定义model实体类

在某些场景下&#xff0c;我们可能需要自定义Flutter model实体类&#xff0c;来创建更加结构化和有组织的代码&#xff0c;提高代码的可重用性&#xff0c;并增强Flutter应用程序的整体可维护性。 自定义小部件:在创建自己的小部件时&#xff0c;可能需要定义自定义数据类型来…...

java项目实现不停服更新的4种方案(InsCode AI 创作助手)

文章目录 1. Blue-Green 部署2. 滚动更新3. 使用负载均衡器4. 灰度发布 在软件开发和维护中&#xff0c;不停机更新是确保应用程序持续可用的关键任务之一。以下是四种常见的不停机更新策略及其示例&#xff1a; 1. Blue-Green 部署 概念&#xff1a; Blue-Green 部署是一种部…...

7.1 yolov5优化模型时,自动标注xml数据

yolov5优化模型时&#xff0c;一般需要继续标注一些检测错误的图片&#xff0c;将其标为xml数据。以下是根据训练好的模型自动标注xml数据的python代码&#xff1a; 注意&#xff1a;代码中包含了本人的yolov5的测试过程&#xff0c;测试过程可以自己根据yolov5的测试文件自行…...

开发者职场“生存状态”大调研报告分析 - 第一版

听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计…...

在MySQL中使用!=还能走索引吗?

在MySQL中使用!还能走索引吗&#xff1f; 一般情况下&#xff0c;我们会在一个索引上较多的使用等值查询或者范围查询&#xff0c;此时索引大多可以帮助我们极快的查询出我们需要的数据。 那当我们在where条件中对索引列使用!查询&#xff0c;索引还能发挥他的作用吗&#xf…...

【算法题】2897. 对数组执行操作使平方和最大

题目&#xff1a; 给你一个下标从 0 开始的整数数组 nums 和一个 正 整数 k 。 你可以对数组执行以下操作 任意次 &#xff1a; 选择两个互不相同的下标 i 和 j &#xff0c;同时 将 nums[i] 更新为 (nums[i] AND nums[j]) 且将 nums[j] 更新为 (nums[i] OR nums[j]) &#…...

2023年中国划船机产量、销量及市场规模分析[图]

划船机是一种健身器材&#xff0c;它模拟了划船的运动&#xff0c;可以锻炼身体的肌肉力量和协调性。划船机通常由座椅、把手、脚踏板和传动装置组成&#xff0c;使用者可以通过拉动把手来模拟划船的动作&#xff0c;从而达到锻炼身体的目的。 划船机产业链 资料来源&#xff…...

Kafka和RabbitMQ的对比

Rabbitmq比kafka可靠&#xff0c;kafka更适合IO高吞吐的处理&#xff0c;比如ELK日志收集 Kafka和RabbitMq一样是通用意图消息代理&#xff0c;他们都是以分布式部署为目的。但是他们对消息语义模型的定义的假设是非常不同的。 a) 以下场景比较适合使用Kafka。如果有大量的事…...

ffmpeg从一个视频中提取音频

ffmpeg -i ~/video/video.mp4 -vn -acodec copy ~/video/audioFile.m4a 从video.mp4中提取音频到文件audioFile.m4a中 查看提取的音频文件 ffprobe ~/video/audioFile.m4a...

CCF CSP题解:坐标变换(其一)(202309-1)

链接 OJ链接&#xff1a;传送门 AC代码 #include <iostream>using namespace std;int n, m;int dx 0, dy 0;int main() {cin >> n >> m;for (int i 0; i < n; i) {int x, y;cin >> x >> y;dx x;dy y;}for (int i 0; i < m; i) {i…...

跳表C语言

【C语言】算法学习跳表_c语言跳表-CSDN博客 leetcode原题&#xff0c;代码如下 #define MAX(a, b) ((a) > (b) ? (a) : (b)) const int MAX_LEVEL 32; const int P_FACTOR RAND_MAX >> 2;typedef struct SkiplistNode {int val;int maxLevel;struct SkiplistNode…...

【JavaEE】_tomcat的安装与简单使用

目录 1. 安装tomcat 1.1 下载tomcat并解压缩 1.2 启动tomcat 1.3 访问tomcat欢迎页面 2. tomcat简单使用&#xff1a;部署前端代码 3. 基于tomcat的网站后端开发 tomcat是一个HTTP服务器&#xff0c;HTTP协议就是HTTP客户端与HTTP服务器之间通信使用的协议。 其中HTTP客…...

React 状态管理 - Context API 前世今生(上)旧版v16.3前

目录 扩展学习资料 Context api before React v16.3 Context 实战使用-Context Context VS Props Context Props Context的缺陷 New Context API 的实践 扩展学习资料 名称 链接 备注 new context api https://reactjs.org/docs/context.html 英文 old context …...

微服务、SOA 和 API 之间的区别

在软件开发中&#xff0c;组织的投资方式发生了重大转变&#xff0c;部署了面向架构的方法。这一切都始于 SOA&#xff0c;然后转变为我们称之为微服务的东西。添加到其中的是另一个概念&#xff0c;指定为 API。 在过去的几年里&#xff0c;SOA 和微服务仍然是讨论的话题。随…...

python打印正反直角三角形

我们用while循环&#xff0c;第一行打印一颗星&#xff0c;第二行打印两颗星&#xff0c;依次循环到五颗 我们写while循环时&#xff0c;先定义一个变量&#xff0c;然后在循环中增加值 i0 while < 5:j0while j <i:print(*,end\t)j1print() # 换行i1我们还可以打印反…...

ubuntu安装Miniconda并举例使用

更新系统包 sudo apt update sudo apt upgrade官网下载Miniconda&#xff0c;最好是实体机下载后放进虚拟机&#xff0c;方法可以参考Xftp 7连接服务器或者本地虚拟机文章 https://docs.conda.io/en/latest/miniconda.html#linux-installers 进入安装目录执行&#xff0c;右键…...

如何保护您的数据免受.360勒索病毒的感染

导言&#xff1a; 网络安全漏洞和威胁伴随着我们的日常生活。其中&#xff0c; 360 勒索病毒成为了引发广泛关注的网络威胁之一。本文91数据恢复将深入探索 360 勒索病毒&#xff0c;揭示它背后的黑暗故事和如何防范此类风险。 如果受感染的数据确实有恢复的价值与必要性&#…...

2024计算机保研--哈工大、中山、国防科大

前言 标题中的学校是我在九月前差不多拿到 o f f e r offer offer&#xff0c;且有可能会去的学校&#xff0c;这篇博客也不能算是经验贴&#xff0c;只能算是血泪史吧。趁着我还记得这几个月的经历&#xff0c;还是记录一下吧&#xff0c;刚才刷知乎看了七月哥&#xff08;是…...

Hadoop分布式集群搭建教程

目录 前言环境准备一、创建虚拟机二、虚拟机网络配置三、克隆虚拟机四、Linux系统配置五、Hadoop的部署配置六、Hadoop集群的启动 前言 大数据课程需要搭建Hadoop分布式集群&#xff0c;在这里记录一下搭建过程 环境准备 搭建Haoop分布式集群所需环境&#xff1a; VMware&a…...

学习函数式编程、可变参数及 defer - GO语言从入门到实战

函数是⼀等公⺠、学习函数式编程、可变参数及 defer - GO语言从入门到实战 函数是⼀等公⺠ 在Go语言中&#xff0c;函数可以分配给一个变量&#xff0c;可以作为函数的参数&#xff0c;也可以作为函数的返回值。这样的行为就可以理解为函数属于一等公民。 与其他主要编程语⾔…...

Linux 文件链接

Linux 下的文件链接有两类。一个是类似于 win 电脑的快捷方式&#xff0c;我们称为软链接&#xff0c;软链接也可以叫做符号链接。另一种是通过文件系统的 inode 连接来产生的&#xff0c;类似于 windows 电脑的复制&#xff0c;但是不产生新的文件&#xff0c;我们称为硬链接。…...

1.go web之gin框架

Gin框架 一、准备 1.下载依赖 go get -u github.com/gin-gonic/gin2.引入依赖 import "github.com/gin-gonic/gin"3. &#xff08;可选&#xff09;如果使用诸如 http.StatusOK 之类的常量&#xff0c;则需要引入 net/http 包 import "net/http"二、基…...

工程物料管理信息化建设(十二)——关于工程物料管理系统最后的思考

目录 1 功能回顾1.1 MTO模块1.2 请购模块1.3 采购模块1.4 催交模块1.5 现场管理模块1.6 数据分析和看板模块1.7 其它模块 2 最后几个问题2.1 按管线发料和直接发料重叠2.2 YHA 材料编码的唯一性问题2.3 “合同量单-箱单-入库单” 数据映射 3 关于未来的思考3.1 三个专业之间的关…...

什么是API网关?——驱动数字化转型的“隐形冠军”

什么是API网关 API网关&#xff08;API Gateway&#xff09;是一个服务器&#xff0c;位于应用程序和后端服务之间&#xff0c;提供了一种集中式的方式来管理API的访问。它是系统的入口点&#xff0c;负责接收并处理来自客户端的请求&#xff0c;然后将请求路由到相应的后端服…...

Java 序列化和反序列化为什么要实现 Serializable 接口?

序列化和反序列化 序列化&#xff1a;把对象转换为字节序列的过程称为对象的序列化. 反序列化&#xff1a;把字节序列恢复为对象的过程称为对象的反序列化. 什么时候需要用到序列化和反序列化呢或者对象序列化的两种用途… &#xff1a; (1) 对象持久化&#xff1a;把对象的…...

【【萌新的SOC学习之GPIO学习 水】】

萌新的SOC学习之GPIO学习 General Purpose I/O 通用I/O zynq-7000 SOC PS 分为四大部分 APU application Processor UintMemoryIO外设Interconnect 内部互联 PL &#xff1a; IO外设 GPIO可以连接通用的设备&#xff08;比如按键&#xff09; 也可以用GPIO模拟其他的协议 GP…...

10-Node.js入门

01.什么是 Node.js 目标 什么是 Node.js&#xff0c;有什么用&#xff0c;为何能独立执行 JS 代码&#xff0c;演示安装和执行 JS 文件内代码 讲解 Node.js 是一个独立的 JavaScript 运行环境&#xff0c;能独立执行 JS 代码&#xff0c;因为这个特点&#xff0c;它可以用来…...

Redis 的过期键 | Navicat 技术干货

Redis 是一种高性能的内存数据存储&#xff0c;以其速度和多功能性而闻名。其中一个有用的特性是为键设置过期时间的功能。在 Redis 中&#xff0c;为键设置过期时间对于管理数据和确保过时或临时数据自动从数据库中删除是至关重要的。在本文中&#xff0c;我们将探讨在 redis-…...

IDC服务器商是如何保护服务器的数据安全

服务器是作为一个公司存储数据和管理服务的设备&#xff0c;随着网络的不断发展大数据的普遍性&#xff0c;所以数据安全问题也越来越受到企业和个体的重视&#xff0c;那么IDC服务器商家是如何对服务器的数据进行安全保护的呢&#xff1f; 配置防火墙。防火墙是服务器的必备工…...

c++中什么时候用double?

c中什么时候用double? 在C中&#xff0c;通常使用double数据类型来表示浮点数&#xff0c;特别是当需要更高的精度时。以下是一些情况下可以考虑使用double的示例&#xff1a; 1. **需要高精度的计算**&#xff1a;当您需要进行精确的浮点数计算时&#xff0c;double通常比flo…...