Flutter自定义model实体类
在某些场景下,我们可能需要自定义Flutter model实体类,来创建更加结构化和有组织的代码,提高代码的可重用性,并增强Flutter应用程序的整体可维护性。
-
自定义小部件:在创建自己的小部件时,可能需要定义自定义数据类型来封装小部件的特定数据和行为。
-
API集成:在使用API时,您可能需要定义自定义数据类型,以便以结构化的方式解析和表示响应数据。这有助于更有效地处理和操作数据。
-
状态管理:在像Provider或Riverpod这样的状态管理解决方案中,你可以定义自定义数据类型来表示应用程序的状态,并相应地更新它。
-
表单验证:在构建表单时,您可能希望定义自定义数据类型来表示表单字段并对输入值执行验证。
一、认识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实体类
在某些场景下,我们可能需要自定义Flutter model实体类,来创建更加结构化和有组织的代码,提高代码的可重用性,并增强Flutter应用程序的整体可维护性。 自定义小部件:在创建自己的小部件时,可能需要定义自定义数据类型来…...
java项目实现不停服更新的4种方案(InsCode AI 创作助手)
文章目录 1. Blue-Green 部署2. 滚动更新3. 使用负载均衡器4. 灰度发布 在软件开发和维护中,不停机更新是确保应用程序持续可用的关键任务之一。以下是四种常见的不停机更新策略及其示例: 1. Blue-Green 部署 概念: Blue-Green 部署是一种部…...
7.1 yolov5优化模型时,自动标注xml数据
yolov5优化模型时,一般需要继续标注一些检测错误的图片,将其标为xml数据。以下是根据训练好的模型自动标注xml数据的python代码: 注意:代码中包含了本人的yolov5的测试过程,测试过程可以自己根据yolov5的测试文件自行…...
开发者职场“生存状态”大调研报告分析 - 第一版
听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计…...
在MySQL中使用!=还能走索引吗?
在MySQL中使用!还能走索引吗? 一般情况下,我们会在一个索引上较多的使用等值查询或者范围查询,此时索引大多可以帮助我们极快的查询出我们需要的数据。 那当我们在where条件中对索引列使用!查询,索引还能发挥他的作用吗…...
【算法题】2897. 对数组执行操作使平方和最大
题目: 给你一个下标从 0 开始的整数数组 nums 和一个 正 整数 k 。 你可以对数组执行以下操作 任意次 : 选择两个互不相同的下标 i 和 j ,同时 将 nums[i] 更新为 (nums[i] AND nums[j]) 且将 nums[j] 更新为 (nums[i] OR nums[j]) &#…...
2023年中国划船机产量、销量及市场规模分析[图]
划船机是一种健身器材,它模拟了划船的运动,可以锻炼身体的肌肉力量和协调性。划船机通常由座椅、把手、脚踏板和传动装置组成,使用者可以通过拉动把手来模拟划船的动作,从而达到锻炼身体的目的。 划船机产业链 资料来源ÿ…...
Kafka和RabbitMQ的对比
Rabbitmq比kafka可靠,kafka更适合IO高吞吐的处理,比如ELK日志收集 Kafka和RabbitMq一样是通用意图消息代理,他们都是以分布式部署为目的。但是他们对消息语义模型的定义的假设是非常不同的。 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链接:传送门 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原题,代码如下 #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简单使用:部署前端代码 3. 基于tomcat的网站后端开发 tomcat是一个HTTP服务器,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 之间的区别
在软件开发中,组织的投资方式发生了重大转变,部署了面向架构的方法。这一切都始于 SOA,然后转变为我们称之为微服务的东西。添加到其中的是另一个概念,指定为 API。 在过去的几年里,SOA 和微服务仍然是讨论的话题。随…...
python打印正反直角三角形
我们用while循环,第一行打印一颗星,第二行打印两颗星,依次循环到五颗 我们写while循环时,先定义一个变量,然后在循环中增加值 i0 while < 5:j0while j <i:print(*,end\t)j1print() # 换行i1我们还可以打印反…...
ubuntu安装Miniconda并举例使用
更新系统包 sudo apt update sudo apt upgrade官网下载Miniconda,最好是实体机下载后放进虚拟机,方法可以参考Xftp 7连接服务器或者本地虚拟机文章 https://docs.conda.io/en/latest/miniconda.html#linux-installers 进入安装目录执行,右键…...
如何保护您的数据免受.360勒索病毒的感染
导言: 网络安全漏洞和威胁伴随着我们的日常生活。其中, 360 勒索病毒成为了引发广泛关注的网络威胁之一。本文91数据恢复将深入探索 360 勒索病毒,揭示它背后的黑暗故事和如何防范此类风险。 如果受感染的数据确实有恢复的价值与必要性&#…...
2024计算机保研--哈工大、中山、国防科大
前言 标题中的学校是我在九月前差不多拿到 o f f e r offer offer,且有可能会去的学校,这篇博客也不能算是经验贴,只能算是血泪史吧。趁着我还记得这几个月的经历,还是记录一下吧,刚才刷知乎看了七月哥(是…...
Hadoop分布式集群搭建教程
目录 前言环境准备一、创建虚拟机二、虚拟机网络配置三、克隆虚拟机四、Linux系统配置五、Hadoop的部署配置六、Hadoop集群的启动 前言 大数据课程需要搭建Hadoop分布式集群,在这里记录一下搭建过程 环境准备 搭建Haoop分布式集群所需环境: VMware&a…...
学习函数式编程、可变参数及 defer - GO语言从入门到实战
函数是⼀等公⺠、学习函数式编程、可变参数及 defer - GO语言从入门到实战 函数是⼀等公⺠ 在Go语言中,函数可以分配给一个变量,可以作为函数的参数,也可以作为函数的返回值。这样的行为就可以理解为函数属于一等公民。 与其他主要编程语⾔…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
