当前位置: 首页 > 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;也可以作为函数的返回值。这样的行为就可以理解为函数属于一等公民。 与其他主要编程语⾔…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

XXE漏洞知识

目录 1.XXE简介与危害 XML概念 XML与HTML的区别 1.pom.xml 主要作用 2.web.xml 3.mybatis 2.XXE概念与危害 案例&#xff1a;文件读取&#xff08;需要Apache >5.4版本&#xff09; 案例&#xff1a;内网探测&#xff08;鸡肋&#xff09; 案例&#xff1a;执行命…...

c++算法学习3——深度优先搜索

一、深度优先搜索的核心概念 DFS算法是一种通过递归或栈实现的"一条路走到底"的搜索策略&#xff0c;其核心思想是&#xff1a; 深度优先&#xff1a;从起点出发&#xff0c;选择一个方向探索到底&#xff0c;直到无路可走 回溯机制&#xff1a;遇到死路时返回最近…...

Unity VR/MR开发-开发环境准备

视频讲解链接&#xff1a; 【XR马斯维】UnityVR/MR开发环境准备【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

如何在Spring Boot中使用注解动态切换实现

还在用冗长的if-else或switch语句管理多个服务实现? 相信不少Spring Boot开发者都遇到过这样的场景:需要根据不同条件动态选择不同的服务实现。 如果告诉你可以完全摆脱条件判断,让Spring自动选择合适的实现——只需要一个注解,你是否感兴趣? 本文将详细介绍这种优雅的…...