# Dart **Repository Path**: swordying/dart ## Basic Information - **Project Name**: Dart - **Description**: Dart 学习笔记 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-07-10 - **Last Updated**: 2025-03-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Dart 学习笔记 - 一种结构化且富有灵活性的编程语言 ## 1. 基本介绍 1. 定义:一种编译型静态语言 2. 特性:通用、跨平台、面向对象 3. 开发商:谷歌 4. 上线时间:2011年10月10日 5. 官方网站:https://dart.dev 6. 中文社区:https://dart.cn 7. 文件扩展名:` .dart ` ### 2. 设计目的 1. 初始:提高网站开发与运行效率 2. 当前:针对客户端优化与跨平台 ## 3. 应用场景 1. 移动应用开发 2. 桌面应用开发 3. 二维游戏开发 ## 4. 安装方法 - 安装 Flutter 时自动安装 ## 5. 注释 ```dart // 单行注释 /// 给注释管理器查看的注释 /* 多行 注释 */ ``` ## 6. 变量 ```dart void main() { // 声明变量 var var_string = "变量"; print(var_string); // 变量 // 变量连接 var new_string = "Dart 使用 \${var_string} 进行 ${var_string} 连接"; print(new_string); // Dart 使用 ${var_string} 进行变量连接 // 获取变量类型 String var_type = var_string.runtimeType.toString(); // String // 变量类型取值为:@todo } ``` ## 7. 数据结构 ### 1. 整型 int - 整数值不超过64位 ```dart void main() { int var_int = 1; print(var_int); // 1 print(var_int.runtimeType.toString()); // int } ``` ### 2. 浮点型 double - 64位(双精度)浮点数字 ```dart void main() { double var_double = 1; print(var_double); // 1.0 print(var_double.runtimeType.toString()); // double // 备注 1:整型转浮点型保留 1 位小数,且小数部分为 0 // 备注 2:浮点型打印时自动格式为小数点后非 0 的浮点数 } ``` ### 3. 字符串 String ```dart void main() { String var_string = 'string'; print(var_string); // string print(var_string.runtimeType.toString()); // String print('字符串使用 + ' + '连接'); } ``` #### 多行字符串 1. 动态定界符 heredoc ```dart void main() { String var_string = 'string'; String heredoc = """ \${var_string} = ${var_string} """; print(heredoc); } ``` 2. 静态定界符 nowdoc ```dart void main() { String var_string = 'string'; String nowdoc = r""" \${var_string} = ${var_string} """; print(nowdoc); } ``` ### 4. 布尔值 bool ```dart void main() { bool var_bool = true; print(var_bool); // true print(var_bool.runtimeType.toString()); // bool } ``` ### 5. 记录 Record - [Dart 3.0]记录是一种匿名、不可变的聚合类型 ```dart void main() { // ## 1. 通过 Record 声明 Record record_record = ('first', second:2, 3, false, last:'true'); print(record_record); // (first, 3, false, last: true, second: 2) // ## 2. 通过 var 声明 var var_record = ('first', second:2, 3, false, last:'true'); print(var_record.runtimeType.toString()); // (String, int, bool, {String last, int second}) print(var_record); // (first, 3, false, last: true, second: 2) // 备注:记录值如何没有记录键声明,则会自动增加索引,并调整记录值的顺序 // 通过键访问记录值 print(var_record.$1); // first print(var_record.last); // true # 字符串 // ## 3. 通过 复合类型 声明 (String, int) string_int = ('年份', 2023); print(string_int); // (年份, 2023) } ``` #### 1. 备注:声明 Record 有三种形式 1. 以 `var` 常规声明,用于声明初始记录,可以访问记录值 2. 以复合类型 ` (int, String, bool) ` 进行声明,可以访问记录值 3. 以 ` Record ` 关键词声明,智能整体访问记录值 #### 2. 备注:记录值调整顺序规律 1. 所有自动增加索引的记录值按声明的顺序调整到记录队首,这些记录称为索引记录 2. 拥有键的记录值按记录键的首字母自然排序,并置于队尾,这些记录称为关联记录,或者以可以称为哈希记录 #### 3. Dart Record 运用示例:判断两个记录值时候想等 ```dart void main() { bool result; // ## 1. 索引记录比较 var record_1 = (1,2); var record_2 = (2,1); result = (record_1 == record_2) ? true : false; print(result); // false // ## 2. 关联记录比较 var record_3 = (a:1, b:2); var record_4 = (b:2, a:1); result = (record_3 == record_4) ? true : false; print(result); // true } ``` ### 6. 列表 List 即 数组 arrays ```dart void main() { // # 1. 常规声明使用 int var list = [1, 2, 3]; print(list.runtimeType.toString()); // List print(list); // [1, 2, 3] print(list[0]); // 1 // # 2. 常规声明使用 string var list_string = ['a', 'b', 'c']; print(list_string.runtimeType.toString()); // List print(list_string[0]); // a // # 3. 常规声明使用 直接指定 int // List var_list = [0,1,2]; List var_list = ['a', 'b', 'c']; print(var_list.runtimeType.toString()); // List // # 4. 常规声明使用 进一步直接指定 list int List list_int = [1, 2, 3]; print(list_int.runtimeType.toString()); // List // # 5. 混合常规声明使用 var var_int_string = [1, 'a']; print(var_int_string.runtimeType.toString()); // List print(var_int_string); // [1, a] print(var_int_string[0]); // 1 // # 5. 混合常规声明使用 List list_int_string = [1, 'a']; print(list_int_string.runtimeType.toString()); // List print(list_int_string); // [1, a] print(list_int_string[0]); // 1 // # 5. dynamic 声明使用 List int_dynamic = [1, 2, 3]; print(int_dynamic.runtimeType.toString()); // List print(int_dynamic); // [1, 2, 3] print(int_dynamic[0]); // 1 // # 6. dynamic 声明使用 List string_dynamic = ['a', 'b', 'b']; // List string_dynamic = [1, 2, 3]; print(string_dynamic.runtimeType.toString()); // List print(string_dynamic); // [a, b, b] print(string_dynamic[0]); // a // # 7. 混合 dynamic 声明使用 List int_string_dynamic = [1, 'a']; print(int_string_dynamic.runtimeType.toString()); // List print(int_string_dynamic); // [1, a] print(int_string_dynamic[0]); // 1 // # 8. Object 声明使用 List int_Object = [1, 2, 3]; print(int_Object.runtimeType.toString()); // List print(int_Object); // [1, 2, 3] print(int_Object[0]); // 1 // # 9. Object 声明使用 List string_Object = ['a', 'b', 'b']; // List string_Object = [1, 2, 3]; print(string_Object.runtimeType.toString()); // List print(string_Object); // [a, b, b] print(string_Object[0]); // a // # 8. 混合 Object 声明使用 List int_string_Object = [1, 'a']; print(int_string_Object.runtimeType.toString()); // List print(int_string_Object); // [1, a] print(int_string_Object[0]); // 1 } ``` #### Dart List 总结 1. 声明 List 可以使用 `List`、`List`、`List` 等常规声明方法 2. 由于 Dart 的数据结构最终都是对象,所以在一定程度上 `List` 可以代替 `List`、`List` 等常规声明 3. `List`: 这是Dart中的动态类型声明。与 `List` 类似,更具有处理不确定的数据的概念 ### 7. 集合 Set - 一系列无序独立且唯一的元素 ```dart void main() { var set = {1, 2}; print(set); // {1, 2} print(set.runtimeType.toString()); // _Set Set set_int = {1, 2}; print(set_int); // {1, 2} print(set_int.runtimeType.toString()); // _Set var var_set_string = {'a', 'b'}; print(var_set_string); // {1, 2} print(var_set_string.runtimeType.toString()); // _Set Set set_string = {'a', 'b'}; print(set_string); // {'a', 'b'} print(set_string.runtimeType.toString()); // _Set var var_set_int_string = {1, 'a'}; print(var_set_int_string); // {1, a} print(var_set_int_string.runtimeType.toString()); // _Set Set set_object_int = {1, 2}; print(set_object_int); // {1, 2} print(set_object_int.runtimeType.toString()); // _Set Set set_object_string = {'a', 'b'}; print(set_object_string); // {'a', 'b'} print(set_object_string.runtimeType.toString()); // _Set Set set_object_int_string = {1, 'a'}; print(set_object_int_string); // {1, 'a'} print(set_object_int_string.runtimeType.toString()); // _Set // 声明集合必须指定类型,即使元素为多种类型,也需要用 Object 修饰,否则会被认定为 Map 数据类型,影响后续操作 var set_default_int = {}; // Set set_default_int = {}; set_default_int.add(1); set_default_int.addAll({1, 2}); print(set_default_int); // {1, 2} Set set_default_string = {'a'}; set_default_string.add(1); set_default_string.addAll({'b', 2}); print(set_default_string); // {a, 1, b, 2} // 检查元素是否在集合中 var is_in_set = set_default_string.contains('a'); print(is_in_set); // true bool is_all_in_set = set_default_string.containsAll({'b', 2}); print(is_all_in_set); // true } ``` #### 总结 1. 因为集合中的元素是无序的,所以没有访问某个元素的方法 2. 因为集合中的元素是唯一的,所以可以判断出元素的存在性 ### 8. 图表 Map - 地图是关联键和值的对象 ```dart void main() { var map = {}; map['first'] = 1; print(map); // {first: 1} print(map.runtimeType.toString()); // _Map print(map['first']); // 1 var map_int_string = {1:'first'}; print(map_int_string); // {1: first} print(map_int_string.runtimeType.toString()); // _Map print(map_int_string[1]); // first Map map_dynamic = {1:1}; print(map_dynamic.runtimeType.toString()); // _Map Map map_object = {1:1}; print(map_object.runtimeType.toString()); // _Map } ``` #### 总结 1. Object 与 dynamic 在一定程度上可以互用 2. Object 的数据调用其方法与属性时,需要经过类型转换 3. dynamic 用于表示运行时动态类型,可以简洁代码,但难以维护 4. 声明变量类型原则:可以确切类型的则使用确切的类型 ### 9. 类 class ```dart void main(){ // 实例化一个 人类 Man man = new Man(18, 'Alice'); print(man.name); // Alice man.getAge(); // 18 man.setAge(20); man.getAge(); // 20 man._setName('Bob'); // 没有做成模块,随意可以访问 print(man.name); // Bob print(man.runtimeType.toString()); // Man // 获取器 man.age; // 如果没有事先定义属性,则必须通过设置器来声明属性 man.age = 4; } /** * -------------------------------- * # 人类 * -------------------------------- * 1. 年龄 * 2. 姓名 * 3. 构造:年龄、姓名 * -------------------------------- */ class Man { // 定义静态属性 static String from = 'earth'; // _ 定义私有属性 int? _age; // 定义普通属性 String? name; // 构造方法 Man(int age, String name) { this._age = age; this._setName(name); } // 普通方法 void getAge() { print(this._age); } void setAge(int age) { this._age = age; } // 私有方法:关键备注:私有方法的类需要放到单独的文件中,通过 import 引入,才能达到私有的效果 void _setName(String name) { this.name = name; } // 获取器 int get age{ return this._age!; } // 设置器 void set age(int value){ this.age = value; } } // 继承 class Child extends Man { Child(super.age, super.name); } ``` #### 总结 - 获取器:设置器的作用不仅仅对本身起作用,更多的是在属性【获取】后作为一个"钩子"使用 - 获取器:设置器的作用不仅仅对本身起作用,更多的是在属性【修改】后作为一个"钩子"使用 1. 声明了属性,则自动定义了获取器与设置器 2. 不声明属性,则需要主动定义获取器设置器 3. Dart 中只有公共与私有封装,且私有封装需要定义在单独的类文件中 ##### Dart 类的构造方法与继承 - Dart 类的构造方法有无参数将影响子类的定义 1. 父类的构造方法有参数,则子类的构造方法必须有参数 2. 父类的构造方法有参数,则子类的构造方法不可以省略 3. 父类的构造方法无参数,子类的构造方法也可以有参数 4. 父类的构造方法无参数,子类的构造方法可以省略 ### 10. 符号 Symbols - 符号(Symbol)是一种特殊的不可变数据类型,用于表示唯一标识符。它们通常用于对象的键,以区分不同的属性或变量。 ```dart void main() { var symbol_1 = Symbol('string'); var symbol_2 = Symbol('string'); result = symbol_1 == symbol_2 ? true : false; print(result); // true print(identical(symbol_1,symbol_2)); // false } ``` ### 11. 符文 Runes 1. 简介:Dart 中的 String 是 UTF-16 字节单元定义的,而有些 Unicode 字符无法用 16 位表示,因此需要使用 Runes 32 位 来表示这些字符; 2. 概念:它可以把文字转换成 符号表情 或 特定的文字; 3. 作用:一些表情符号、某些特殊的数学符号或者某些非常罕见的语言字符等 ```dart void main() { // 特殊字符 与 Unicode 唯一位点码 互相转换 String smile = '😊'; Runes smile_string_to_runes = smile.runes; String smile_runes_to_string = new String.fromCharCodes(smile_string_to_runes); print(smile); // 😊 print(smile_string_to_runes); // (128522) print(smile_string_to_runes.runtimeType); // Runes print(smile_runes_to_string); // 😊 } ``` #### 总结:Dart 中对于大部分 Unicode 直接使用即可,尤其对于表情符号 ### 常用数据结构的转化 #### 1. 标量之间的转化 ```dart void main(){ // 整数 -> 浮点数 print('## 1.'); print(1.toDouble()); // 1.0 // 整数 -> 布尔 print('## 2.'); print(1 != 0); // true // 整数 -> 字符串 print('## 3.'); print(1.toString()); // '1' // 浮点数 -> 整数 print('## 4.'); double var_double = 1.1; print(var_double.toInt()); // 1 // 浮点数 -> 布尔 print('## 5.'); print(1.1 != 0.0); // true // 浮点数 -> 字符串 print('## 6.'); print(1.1.toString()); // '1.1' print(1.1.toString().runtimeType); // String // 字符串 -> 整数 print('## 7.'); print(int.parse('111')); // 111 print(int.parse('111').runtimeType); // int // 非纯数字字符串转化为整数需要额外操作,没有直接的语法糖 // 字符串 -> 浮点数 print('## 8.'); print(double.parse('1.1')); // 1.1 print(double.parse('1.1').runtimeType); // double // 非纯数字字符串转化为浮点数需要额外操作,没有直接的语法糖 // 字符串 -> 布尔 print('## 9.'); print(bool.parse('true')); // true print(bool.parse('true').runtimeType); // bool print(bool.parse('false')); // false print(bool.parse('false').runtimeType); // bool // 布尔 -> 整数 print('## 10.'); var_bool = true; // ignore: dead_code print( var_bool ? 1 : 0 ); // ignore: dead_code print( false ? 1 : 0 ); // 布尔 -> 浮点数 print('## 11.'); // ignore: dead_code print( var_bool ? 1.0 : 0.0 ); // 1.0 // ignore: dead_code print( false ? 1.0 : 0.0 ); // 0.0 // ignore: dead_code print( (false ? 1.0 : 0.0).runtimeType ); // double // 布尔 -> 字符串 print('## 12.'); print( true.toString() ); // 'true' print( false.toString() ); // 'false' print( false.toString().runtimeType ); // String } ``` 1. 非纯数字型字符串,没有直接转化为数字的方法 2. Dart 中 字符串 'false' 转化为 布尔 时为 (false)假 3. Dart 中 字符串只有 'true' 与 'false' 能直接转化为 布尔 4. 布尔值可以转化为任意类型,因为可以三元运算 #### 2. 数组与对象转化 ```dart void main(){ // 图表 -> 数组 var map_to = {'key1':'value',1:1}; var array_result = [...map_to.values]; print(array_result); // [value, 1] // 图表 -> 类 // 类 -> 数组 // 类 -> 图表 } ``` #### 总结 1. Dart 中数据转化语法糖比较有限 2. Dart 在数据转化之前应知其目的 ## 8. 流程控制 ### 1. 判断语句 ```dart void main() { if(array_result[0] == 'value'){ print('if 语句'); }else if(array_result[1] == 1){ print('else if 语句'); }else{ print('else 语句'); } } ``` ### 2. 循环语句 #### 1. while 循环 ```dart void main(){ var while_num = 10; var current_num = 1; while(current_num <= while_num){ print(current_num); current_num++; } } ``` #### 2. for 循环 ```dart void main(){ for(var for_i = 1; for_i <= 10; for_i++){ if(for_i == 5){ continue; } print(for_i); if(for_i == 9){ break; } } } ``` ### 3. 中断语句 #### 1. break 终止当前循环 #### 2. continue 立即执行下一次循环 ## 9. 面向对象 ### 1. 面向对象特性 1. 封装:Dart 提供了关键字 "_" 来标识私有成员 2. 继承:Dart 通过 ` extends ` 关键词,实现继承 3. 多态:不同子类可以独立实现父类的同名方法 - 继承是多态的手段、多态是继承的目的 ### 2. 封装原则 1. Dart 提供了关键字 "_" 来标识私有成员 2. Dart 中只有公共与私有封装,且私有封装需要定义在单独的类文件中 ### 3. 代码示例 - 通过 数据结构 class 体现 ## 10. 常量 ### 1. 使用 const 定义常量 - 编译时就需要确定 ```dart const double pi = 3.14; const List numbers = [1, 2, 3]; print(numbers.runTimetype); // List print(numbers); // [1, 2, 3] ``` ### 2. 使用 final 定义常量 - 只能被赋值一次的变量,可以在运行代码时确定 ```dart final e; e = 2.71828; void main() { print(e); // 2.71828 print(e.runTimetype); // } ``` ## 11. 函数 ### 1. 声明函数 ```dart void echo(var string){ print(string); } ``` ### 2. 使用函数 ```dart void main(){ echo('string'); } ``` ## 12. 异常处理 ` try...throw...catch ` ```dart void main(){ try { throwException(); } catch (e) { print('捕获到异常: ' + e); } } void throwException() { throw '这是一个异常'; } ``` ### 总结 1. Dart 异常处理通常不解决编译时的异常,而是解决运行时的相关异常 2. 在复杂的程序中,if-else 和异常处理通常会结合使用来解决相关问题 ### 2. 内置异常处理类 ## 13. 类库引入 - Dart 中通过 ` import ` 关键字来引入类库 ```dart import '路径/文件名称'; ``` ### 内置类库 1. dart:io:这个库提供了输入/输出(I/O)相关的类和函数。它允许开发者进行文件操作、网络编程、进程管理等。 2. dart:core:这是 Dart 的核心库,提供了大多数基本数据类型和函数,如数字、字符串、集合、迭代器等。 3. dart:math:这个库提供了数学计算相关的类和函数。开发者可以使用它来进行数值计算、生成随机数、进行三角函数计算等。 4. dart:convert:这个库提供了各种数据编码和解码相关的类和函数。开发者可以使用它来处理 JSON、XML、UTF-8 编码等。 5. dart:async:这个库提供了管理异步操作的类和函数。它允许开发者创建和处理 Future 对象、实现异步流和定时器等。 ## 14. 文件操作 - Dart 中文件操作最好知道是文件还是目录 ### 1. 普通文件操作 ```dart import "dart:io"; void main() { // 使用 File 类创建一个新文件 File file = File(test_txt); // 如果文件不存在,则创建它 if (!file.existsSync()) { // 1. 同步创建文件 file.createSync(); } // 2. 读取文件 file.readAsString().then((String contents) { print(contents); }); // 3. 写入文件 String contents = '文件内容'; // 异步-覆盖写入文件 file.writeAsString(contents); // 异步-文件追加内容,mode: FileMode.append file.writeAsString(contents, mode: FileMode.append); // 同步-文件追加内容,mode: FileMode.append file.writeAsStringSync(contents, mode: FileMode.append); // 4. 文件信息 FileStat file_status = file.statSync(); // 4-1. 文件全路径 var file_full_path = file.path; print( file_full_path ); // 4-2. 文件名称 var file_name = file.path.substring(file.path.lastIndexOf('/') + 1, file.path.lastIndexOf('.')); print( file_name ); // 4-3. 文件类型 print( file_status.type ); // 4-4. 文件大小 print( file_status.size ); // 4-5. 文件最后修改时间 print( file_status.modified ); // 4-6. 文件扩展名,无快捷方法 var file_extension = file.path.substring(file.path.lastIndexOf('.') + 1); print(file_extension); // 4-7. 文件创建时间 // dart 中不支持获取文件的创建时间,终端:MacOS // 5. 删除文件 file.delete(); } ``` ### 2. 目录操作 ```dart // 读取目录 String test_path; Directory test_directory = Directory(test_path); // 1. 如果目录不存在则创建目录 if( !test_directory.existsSync() ){ // 创建目录 test_directory.create(); } // 2. 迭代目录 List entities = directory.listSync(); for ( FileSystemEntity entity in entities ) { print(entity.path); } // 3. 检查文件-是否存在 var is_file = FileSystemEntity.isFileSync(test_txt); var is_dir = FileSystemEntity.isDirectorySync(test_txt); // 如果既不是文件也不是目录,说明此文件或目录不存在 // 4. 删除目录 test_directory.delete(); ``` ## 15. 数据库操作 1. 数据库 MySQL 操作需要第三方类库解决,常用的为 mysql1 2. 通常数据库操作使用的是 ORM 框架,如 Moor 和 DartORM 3. 作为前端开发,通常需要操作 Sqlite ### 1. Dart 操作 Sqlite - 使用 sqflite 库来操作 SQLite 数据库,需要基于 Flutter ## 16. Dart JSON 操作 ## 17. Dart 图片操作 ## 附录其他 1. Dart 中文网 https://dart.cn 2. Dart 官网 https://flutter.dev