dart 学习
| 名称 | 连接 | 备注 |
|---|---|---|
| Flutter中文官网 | https://flutterchina.club | |
| Flutter中文官方安装教程 | https://flutterchina.club/get-started/install/ | |
| dart官方语言 | https://dart.cn/ | |
| flutter官方文档 | https://docs.flutter.dev/get-started/install | |
| flutter官方的中文文档 | https://docs.flutter.cn/release/archive |
1.简介
1.1 简介
Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter 提供了丰富的组件、接口,开发者可以很快地为 Flutter 添加 Native(即原生开发,指基于平台原生语言来开发应用,flutter可以和平台原生语言混合开发) 扩展。下面我们整体介绍一下 Flutter 技术的主要特点。
1.2 安装flutter
由于Flutter会同时构建Android和IOS两个平台的发布包,所以Flutter同时依赖Android SDK和iOS SDK,在安装Flutter时也需要安装相应平台的构建工具和SDK。都是以下三步
- flutter sdk
- Android sdk
- Xcode sdk
1.2.1 mac安装
Flutter sdk安装
目前新版版的flutter是包含 dart 环境的,无需额外安装
点击:https://docs.flutter.cn/release/archive
选择自己的版本并且下载

首先解压安装包

然后把下面的安装路径给替换 $PWD就是
cat <<EOT >> ~/.zprofile
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
export PATH="$PWD/flutter/bin:$PATH"
EOT替换成真正的安装路径
cat <<EOT >> ~/.zprofile
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
export PATH="/Users/luckincoffee/Desktop/app/flutter/bin:$PATH"
EOT然后让配置环境生效
source ~/.zprofile运行 Flutter doctor 来验证安装。
flutter doctor
第一个❌ 是因为没安装Android sdk 暂时先忽略 第二个❌是没安装xcode,安装最新的xcode
安装android sdk
https://developer.android.com/studio?hl=zh-cn

SDK Command-line Tools 安装;其他的配置根据自己情况勾选安装;

随后在终端执行:
这个提示代表Android 许可证状态未知,让我们运行flutter doctor --android-licenses来解决。
按照提示执行
flutter doctor --android-licenses最后执行flutter doctor -> 查看Adnroid 配置是否完成;

安装mac sdk-xcode
https://developer.apple.com/download/all

不知道选择什么版本的,看这个页面数据:https://developer.apple.com/cn/support/xcode/
数据比较大

安装完成后在终端执行:flutter doctor ->查看xcode是否配置成功
下载完毕后,一定要移动到这里,然后再开始安装

选择平台,点击安装,速度非常慢

然后运行代码
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunchflutter doctor 最终效果

https://developer.apple.com/documentation/xcode-release-notes/xcode-15_3-release-notes
Mac
brew install --cask flutter参考资料
https://blog.csdn.net/weixin_46418118/article/details/140719665
1.2.2 windows安装
1.3 编译器
Android Studio
安装插件
Flutter插件: 支持Flutter开发工作流 (运行、调试、热重载等)。Dart插件: 提供代码分析 (输入代码时进行验证、代码补全等)。


vscode
安装插件

体验热重载
- 打开
lib/main.dart文件。 - 将字符串
'You have pushed the button this many times:'更改为'You have clicked the button this many times:'。 - 不要按“停止”按钮; 让您的应用继续运行。
- 要查看您的更改,直接保存(
cmd+s/ctrl+s),或者点击 热重载按钮 (绿色圆形箭头按钮)即可。
你会立即在运行的应用程序中看到更新的字符串。
2. dart语言
在线dart编译器,基本上打不开:https://dartpad.dev/
我们创建完成项目后,学习一下dart语言

执行命令即可运行
dart test.dart
2.1 入门
参考资料
https://blog.csdn.net/weixin_62700590/article/details/139327817
1) 入口函数main
void main(){
print("hello world");
}2) 注释
单行注释
// Symbol libraryName = new Symbol('dart.core');多行注释
/*
* Symbol
*
Symbol libraryName = new Symbol('dart.core'); MirrorSystem mirrorSystem = currentMirrorSystem(); LibraryMirror libMirror = mirrorSystem.findLibrary(libraryName); libMirror.declarations.forEach((s, d) => print('$s - $d'));
*/文档注释
///
main函数 /// /// 符号 /// 枚举 /// void main() { ... }
类、函数 请用 /// 方式定义,后期导出文档有帮助
3) 函数
定义,调用
int add(int x) {
return x + 1;
}
void main(){
// 打印
print(add(1));
}可选参数
int add(int x, [int y = 1, int z = 2]) {
return x + y;
}
void main(){
// 打印
print(add(1));
}可选参数:
使用方括号 [] 来定义可选参数 y 和 z。调用函数时可以选择传入或者不传入这两个参数。
可空类型:
int? 表示 int 类型的值可以是 null。如果没有使用 int?,那么 Dart 不允许把 null 赋值给该参数。
默认值逻辑:
在函数内部,通过 if (y == null) 和 if (z == null) 检查 y 和 z 是否为 null,如果是则赋值为默认的 1。
命名参数 默认值
int add({int x = 1, int y = 1, int z = 1}) {
return x + y + z;
}
void main(){
// 打印
print(add(x:1,y:3,z: 4));
}这个会比可选参数更灵活,可以调用的时候再指定传参
函数内定义
void main(){
int add(int x){
return x + x;
}
print(add(1));
}Funcation 返回函数对象
Function makeAdd(int x) {
return (int y) => x + y;
}
void main(){
// 打印
var add = makeAdd(1);
print(add(5));
}匿名函数
void main(){
// 打印
const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
}
作用域
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}注意 nestedFunction() 函数可以访问包括顶层变量在内的所有的变量。简单说就是被包含的作用域内可以访问包含其的外部变量
4) 数据类型
在 Dart 中,基本类型包括以下几种:int、double、num、bool、String、List、Set、Map、Rune、Symbol、Null。这些类型构成了 Dart 中最核心的部分,开发者可以使用这些类型来处理几乎所有常见的任务。以下是对每种类型的详细说明。
数值类型(int、double、num)
int:表示整数,值没有小数部分,适用于处理不带小数的数值。double:表示浮点数,适用于包含小数部分的数值。num:是int和double的父类,它可以存储任何数值(整数和浮点数)。
| 类型 | 描述 | 示例 |
|---|---|---|
int | 整数类型 | int a = 10; |
double | 浮点数类型 | double b = 3.14; |
num | 数值类型(包含整数和浮点数) | num c = 10; 或 num d = 3.14; |
示例:
void main() {
int age = 30;
double height = 1.75;
num weight = 68.5;
print("Age: $age"); // 输出:Age: 30
print("Height: $height"); // 输出:Height: 1.75
print("Weight: $weight"); // 输出:Weight: 68.5
}布尔类型 (bool)
bool 表示布尔类型,有两个可能的值:true 和 false。布尔类型常用于条件判断和逻辑运算。
| 类型 | 描述 | 示例 |
|---|---|---|
bool | 布尔类型 | bool isActive = true; |
示例
void main() {
bool isLoggedIn = true;
bool hasAccess = false;
if (isLoggedIn) {
print('User is logged in.'); // 输出:User is logged in.
}
if (!hasAccess) {
print('Access denied.'); // 输出:Access denied.
}
}字符串类型 (String)
String 用于表示文本。它是不可变的,也就是一旦创建,字符串内容不能修改。可以使用单引号或双引号来定义字符串。
| 类型 | 描述 | 示例 |
|---|---|---|
String | 字符串 | String name = 'Dart'; |
示例
void main() {
String greeting = 'Hello';
String name = "Dart";
String message = '$greeting, $name!'; // 使用插值
print(message); // 输出:Hello, Dart!
}列表类型 (List)
Dart 提供了三种主要的集合类型:List(列表)、Set(集合)和 Map(映射)。
List 是一个有序的集合,可以包含重复的元素。可以通过索引来访问和修改列表中的元素。
| 类型 | 描述 | 示例 |
|---|---|---|
List | 列表类型 | List<int> numbers = [1, 2, 3]; |
void main() {
List<String> fruits = ['Apple', 'Banana', 'Orange'];
print(fruits[0]); // 输出:Apple
fruits.add('Mango');
print(fruits); // 输出:[Apple, Banana, Orange, Mango]
}集合类型 (Set)
Set 是一个无序且元素唯一的集合。它不会包含重复的元素
| 类型 | 描述 | 示例 |
|---|---|---|
Set | 集合类型 | Set<int> uniqueNumbers = {1, 2, 3}; |
示例
void main() {
Set<int> numbers = {1, 2, 3, 3};
print(numbers); // 输出:{1, 2, 3}
numbers.add(4);
print(numbers); // 输出:{1, 2, 3, 4}
}映射类型 (Map)
Map 是键值对的集合,用于存储关联数据。每个键只能对应一个值。
| 类型 | 描述 | 示例 |
|---|---|---|
Map | 映射类型 | Map<String, int> ages = {'Alice': 30, 'Bob': 25}; |
void main() {
Map<String, int> ages = {'Alice': 30, 'Bob': 25};
print(ages['Alice']); // 输出:30
ages['Charlie'] = 20;
print(ages); // 输出:{Alice: 30, Bob: 25, Charlie: 20}
}符号类型 (Symbol)
Symbol 类型表示 Dart 程序中的操作符或标识符。符号类型在反射和代码生成时非常有用。
| 类型 | 描述 | 示例 |
|---|---|---|
Symbol | 符号类型 | Symbol symbol = #foo; |
示例
void main() {
Symbol symbol = #foo;
print(symbol); // 输出:Symbol("foo")
}Runes
Runes 用于表示 Unicode 字符。Dart 的 String 是 UTF-16 编码的字符串,但有些 Unicode 字符超出这个范围,这时需要使用 Runes 来处理。
| 类型 | 描述 | 示例 |
|---|---|---|
Runes | Unicode 字符 | Runes input = Runes('😀'); |
示例
void main() {
Runes heart = Runes('\u2665'); // 使用 Unicode
print(String.fromCharCodes(heart)); // 输出:♥
}空类型 (Null)
Null 类型表示没有值。在 Dart 2.12 之后,启用了空安全(null safety),使得变量默认不可为空。这意味着在 Dart 中,除非明确声明,否则变量不能存储 null 值。
示例
void main() {
int? age = null; // 使用 `?` 允许变量为空
print(age); // 输出:null
age = 30;
print(age); // 输出:30
}5) 变量
在Dart 中,变量用于存储数据。Dart 是一种强类型语言,这意味着每个变量都有一个明确的类型。尽管 Dart 有类型推断的功能,但理解并正确使用变量的声明和类型是非常重要的。
变量的声明
Dart 中声明变量的常用关键字有 var、final 和 const。
va r
类似于 JavaScript 中的var,它可以接收任何类型的变量,但最大的不同是 Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型,如:
var t = "hi world";
// 下面代码在dart中会报错,因为变量t的类型已经确定为String,
// 类型一旦确定后则不能再更改其类型。
t = 1000;上面的代码在 JavaScript 是没有问题的,前端开发者需要注意一下,之所以有此差异是因为 Dart 本身是一个强类型语言,任何变量都是有确定类型的,在 Dart 中,当用var声明一个变量后,Dart 在编译时会根据第一次赋值数据的类型来推断其类型,编译结束后其类型就已经被确定,而 JavaScript 是纯粹的弱类型脚本语言,var 只是变量的声明方式而已。
使用 final 声明的变量只能赋值一次,之后不能再修改该变量的值。
final city = '北京'; // city 的值不能再被更改const 关键字声明的变量在编译时就已确定为常量,不能被修改。const 常量与 final 的区别是:const 是编译时常量,final 是运行时常量。
const pi = 3.14159; // pi 的值在编译时就被确定了dynamic 和 Object
Object 是 Dart 所有对象的根基类,也就是说在 Dart 中所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象。 dynamic与Object声明的变量都可以赋值任意对象,且后期可以改变赋值的类型,这和 var 是不同的,如:
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//下面代码没有问题
t = 1000;
x = 1000;dynamic与Object不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错,如:
dynamic a;
Object b = "";
main() {
a = "";
printLengths();
}
printLengths() {
// 正常
print(a.length);
// 报错 The getter 'length' is not defined for the class 'Object'
print(b.length);
}dynamic 的这个特点使得我们在使用它时需要格外注意,这很容易引入一个运行时错误,比如下面代码在编译时不会报错,而在运行时会报错:
print(a.xx); // a是字符串,没有"xx"属性,编译时不会报错,运行时会报错2.2 操作符
算术操作符
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
+ | 加法 | 5 + 3 | 8 |
- | 减法 | 5 - 3 | 2 |
* | 乘法 | 5 * 3 | 15 |
/ | 除法 | 5 / 2 | 2.5 |
~/ | 整数除法 | 5 ~/ 2 | 2 |
% | 取余数 | 5 % 2 | 1 |
-expr | 一元负号 | -a | 取反 a 的值 |
赋值操作符
赋值操作符用于将值赋给变量,并支持与算术操作符结合的复合赋值操作。
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
= | 赋值 | a = b | 将 b 赋给 a |
+= | 加法赋值 | a += b | a = a + b |
-= | 减法赋值 | a -= b | a = a - b |
*= | 乘法赋值 | a *= b | a = a * b |
/= | 除法赋值 | a /= b | a = a / b |
~/= | 整数除法赋值 | a ~/= b | a = a ~/ b |
%= | 取余赋值 | a %= b | a = a % b |
??= | 空值赋值 | a ??= b | 如果 a 为 null,则赋值 b |
示例
void main() {
int a = 5;
a += 3; // 相当于 a = a + 3
print(a); // 输出: 8
double b = 10.0;
b /= 2; // 相当于 b = b / 2
print(b); // 输出: 5.0
String? name;
name ??= 'Dart'; // 如果 name 为 null,则赋值 'Dart'
print(name); // 输出: Dart
}比较操作符
比较操作符用于比较两个值,结果为布尔值 true 或 false。
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
== | 等于 | a == b | 如果 a 等于 b,则为 true |
!= | 不等于 | a != b | 如果 a 不等于 b,则为 true |
> | 大于 | a > b | 如果 a 大于 b,则为 true |
< | 小于 | a < b | 如果 a 小于 b,则为 true |
>= | 大于等于 | a >= b | 如果 a 大于等于 b,则为 true |
<= | 小于等于 | a <= b | 如果 a 小于等于 b,则为 true |
示例
void main() {
int a = 5;
int b = 3;
print(a == b); // 输出: false
print(a != b); // 输出: true
print(a > b); // 输出: true
print(a < b); // 输出: false
print(a >= b); // 输出: true
print(a <= b); // 输出: false
}逻辑操作符
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
&& | 逻辑与 | a && b | a 和 b 都为 true,结果为 true |
| | | | ` | ||
! | 逻辑非 | !a | a 为 true,结果为 false |
void main() {
bool a = true;
bool b = false;
print(a && b); // 输出: false
print(a || b); // 输出: true
print(!a); // 输出: false
}位操作符
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
& | 按位与 | a & b | 对 a 和 b 的每一位执行与操作 |
| ` | ` | 按位或 | `a |
^ | 按位异或 | a ^ b | 对 a 和 b 的每一位执行异或操作 |
~expr | 按位取反 | ~a | 对 a 的每一位取反 |
<< | 左移 | a << b | 将 a 的二进制位左移 b 位 |
>> | 右移 | a >> b | 将 a 的二进制位右移 b 位 |
>>> | 无符号右移 | a >>> b | 无符号右移 b 位(Dart 2.14 引入) |
void main() {
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
print(a & b); // 输出: 1 (0001)
print(a | b); // 输出: 7 (0111)
print(a ^ b); // 输出: 6 (0110)
print(~a); // 输出: -6 (取反)
print(a << 1); // 输出: 10 (1010)
print(a >> 1); // 输出: 2 (0010)
}类型测试操作符
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
is | 检查对象是否为指定类型 | a is int | 如果 a 是 int 类型,结果为 true |
is! | 检查对象是否不是指定类型 | a is! String | 如果 a 不是 String 类型,结果为 true |
as | 类型转换 | a as String | 将 a 转换为 String 类型(如果类型不匹配会抛出异常) |
示例
void main() {
dynamic a = 'Hello';
if (a is String) {
print('a 是字符串');
}
String b = a as String;
print(b); // 输出: Hello
}条件表达式
三元运算符
条件表达式用于根据条件的真假来选择性地执行代码。
语法:condition ? expr1 : expr2
当 condition 为 true 时,结果为 expr1;否则结果为 expr2。
void main() {
int a = 5;
String result = (a > 3) ? '大于3' : '小于等于3';
print(result); // 输出: 大于3
}空值合并运算符
| 操作符 | 描述 | 示例 | 结果 |
|---|---|---|---|
?? | 如果左侧值为 null,返回右侧值 | a ?? b | 如果 a 为 null,结果为 b |
??= | 如果变量为 null,赋值右侧值 | a ??= b | 如果 a 为 null,则 a = b |
示例:
void main() {
String? name;
String greeting = 'Hello, ' + (name ?? 'Guest');
print(greeting); // 输出: Hello, Guest
name ??= 'Dart';
print(name); // 输出: Dart
}级联操作符
级联操作符用于对同一个对象连续执行多个操作。
| 操作符 | 描述 | 示例 |
|---|---|---|
.. | 级联操作符 | object..method1()..method2() |
?.. | 空安全级联操作符 | object?..method() |
示例:
class Builder {
int? width;
int? height;
String? color;
void setWidth(int w) => width = w;
void setHeight(int h) => height = h;
void setColor(String c) => color = c;
}
void main() {
Builder builder = Builder()
..setWidth(100)
..setHeight(200)
..setColor('red');
print('宽度: ${builder.width}, 高度: ${builder.height}, 颜色: ${builder.color}');
// 输出: 宽度: 100, 高度: 200, 颜色: red
}访问操作符
用于访问对象的属性或方法,或调用函数。
| 操作符 | 描述 | 示例 |
|---|---|---|
. | 访问成员 | object.property |
?. | 空安全访问成员 | object?.property |
[] | 访问集合的元素 | list[index] |
?[] | 空安全访问集合的元素 | list?[index] |
() | 调用函数或方法 | function() |
示例
void main() {
List<int>? numbers;
print(numbers?[0]); // 输出: null,不会抛出异常
numbers = [1, 2, 3];
print(numbers[0]); // 输出: 1
}扩展操作符
用于在集合中插入另一个集合的所有元素。
| 操作符 | 描述 | 示例 |
|---|---|---|
... | 扩展运算符 | [...list] |
...? | 空安全扩展运算符 | [...?list] |
void main() {
List<int> list1 = [1, 2, 3];
List<int>? list2;
List<int> combinedList = [0, ...list1, ...?list2];
print(combinedList); // 输出: [0, 1, 2, 3]
}异步操作符
await 和 async
用于处理异步操作。
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return '数据加载完成';
}
void main() async {
print('开始加载');
String data = await fetchData();
print(data); // 输出: 数据加载完成(延迟2秒)
}yield 和 yield*
用于生成器函数。
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
yield i;
}
}
void main() async {
await for (int i in countStream(3)) {
print(i); // 输出: 1 2 3
}
}操作符重载
Dart 允许在类中重载部分操作符,使其适用于自定义对象。
可重载的操作符包括:
- 算术操作符:
+、-、*、/、~/、% - 比较操作符:
==、>、<、>=、<= - 位操作符:
&、|、^、~、<<、>> - 索引操作符:
[]、[]= - 一元操作符:
-、~
参考资料:https://blog.csdn.net/ljguo2008/article/details/142320378
2.4 流程控制
if else;for;while;do while;switch case;break;continue;相信这些就不用博主多说了哈
值得一提的是 continue 有一点不一样
continue 跳转指定位置(就像cpp的go to,新增了这个功能)
String command = "close";
switch (command) {
case "open":
print("open");
break;
case "close":
print("close");
continue doClear;
case "close2":
print("close2");
continue doClear;
doClear:
case "doClose":
print("doClose");
break;
default:
print("other");
}2.5 异常
使用 try-catch 捕获异常
try-catch 语句用于捕获并处理抛出的异常。try 块中的代码如果抛出异常,程序将跳转到 catch 块进行处理。
try {
// 可能会抛出异常的代码
} catch (e) {
// 捕获并处理异常
}异常处理的 finally 块
finally 块用于定义无论是否抛出异常都要执行的代码。它通常用于关闭资源或释放占用的资源,例如文件或网络连接。
try {
// 可能抛出异常的代码
} catch (e) {
// 捕获异常
} finally {
// 始终执行的代码
}使用 on 捕获特定异常
如果知道某个代码段可能抛出的具体异常类型,使用 on 来捕获特定异常比使用 catch 更加高效且明确
void main(){
try {
throw new OutOfMemoryError();
} on OutOfMemoryError {
print('没有内存了');
rethrow;
} catch (e) {
print("捕获异常");
print(e);
} finally {
print('end');
}
}2.6 类
class Animal {
String name;
int age;
String color;
Animal(this.name, this.age, this.color);
void eat() {
print("$name is eating");
}
void run() {
print("$name is running");
}
}主函数
import 'lib/Animal.dart';
void main() {
Animal animal = new Animal("Dog", 2, "Black");
animal.eat();
animal.run();
}
导入系统的库
import 'dart:math';
void main() {
var random = Random();
print(sqrt(16));
print(max(10, 20));
print(min(10, 20));
print(random.nextInt(10));
print(random.nextDouble());
print(random.nextBool());
}注解
在 Dart 中,注解(Annotations)是一种元数据,可以为代码中的类、字段、方法、参数等添加附加信息。注解通常用于标记代码中的特定元素,以影响编译、运行时行为,或供框架和工具进行处理。注解以@符号开头,紧跟着一个标识符,或者是一个调用构造函数的表达式。
Dart 中的注解与 Java 等其他语言的注解类似。它们可以用于代码生成、编译时检查、反射等场景,常用于构建器、测试框架等。
Dart 提供了一些内置的注解,常见的有以下几种:
- @override:用于标明一个方法重写了父类中的方法。
- @deprecated:标记某个元素为过时的,会在使用时触发编译器警告。
- @required:用于标记一个命名参数是必需的(Dart 2.12 以前使用,现已被 required 修饰符代替)。
- @pragma:影响编译器的行为,通常不直接使用。
参考教程 https://blog.csdn.net/ljguo2008/article/details/142320378