抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Dart语言学习之路

00初识Dart语言

介绍

dart语言是google公司创建的语言,属于静态编译型语言,但在开发工程中也可以启用动态编译执行的模式,一般搭配flutter框架,用于构建跨平台的App开发,

flutter介绍

Flutter 是 Google 开源的一个用于构建高性能、高质量原生界面应用程序的软件开发工具包

Flutter 目的是用一套代码同时以上多个平台开发原生质量的应用程序

开发效率:只需要一套Dart代码,即可编译生成原生性能的各类平台(Android/I0S/HarmonyOS/。)应用

市场份额:Flutter 以46% 的开发者采用率稳居跨平台框架首位

企业应用:全球已经发布了50w+款应用采用Flutter技术开发,其中15%占比为大厂应用

国产操作系统鸿蒙兴起,企业需要更多的鸿蒙人才具备跨平台能力

接下来需要学习的

dart

image-20260121093557603

flutter

image-20260121093643311

单词表

关键字 程序中的用法 英语翻译
final 定义运行时不可被修改的常量 最后

01DartSDK的安装

下载https://dart.cn/get-dart

根据自己的环境添加环境变量,官网也有教程

02基础

020初始化文件

dart编译的入口入Java,需要从一个mian方法开始

1
2
3
4
5
void main(List<String> args) {
for (int i = 0; i < 10; i++) {
print(i);
}
}

规则

每一行dart代码的结尾都需要有一个分号进行结束语句,但是花括号{}前后边不需要分号进行结束语句

0201注释

1
2
3
4
5
6
// 双斜杠为注释,单行注释

/*
多行注释
。。。
*/

0202打印

1
print("hello World");

0203变量

var变量关键字

var关键字用于在代码中定义变量

  • 初次定义变量后其变量的类型会被固定,且固定了储存值的类型

  • 变量的值不能赋值给常量

    1
    2
    var num1 = 10;
    const num2 = num1; // 是不被允许的

const编译时常量

const关键字用于定义常量

定义后会在代码 编译前 被确定

1
2
3
const pi = 3.14;

print('π的值经常使用' + pi.toString() + "作为运算值")

final运行时常量

final关键字也是用于定义常量

定义后在会在 运行时 被初始化且不可修改

使用场景:当我们需要 当前时间 作为当前唯一的操作时间,时间一旦被确定就不可以被修改

1
2
3
final time = DateTime.now();

print(time); // 当前时间

constfinal 的区别:

const定义后会在代码 编译前 被确定

final定义后在会在 运行时 初始化且不可被修改

0203常用数据类型

String字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
void main() {
String text = "今天是个好日子"; // 是一个var变量
print(text); // 今天是个好日子
text = "明天也是个好日子";
print(text); // 明天也是个好日子
final time = DateTime.now(); // 定义当前时间
// 模板字符串
String content = '我要在$time吃饭'; // 写法一
String content2 = '我要在${DateTime.now()}打游戏'; // 写法二 推荐 如果在字符串中要嵌入表达式时
print(content);
print(content2);
}

数字类型int num double

int:整型数字

num:可整形可小数

double:小数

语法: int/num/double 属性名 = 数值;

数字之间的赋值关系
  • double和int不能直接赋值,但是可以转换后赋值
  • num不能直接给double赋值,但也可以转换后赋值
  • double可以直接给num赋值

容纳关系:

num > double

num > int

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void main() {
int firindCount = 3;
print('我有$firindCount个朋友');
num rest = 1.5;
print('我又${rest}个月的假期');
double appleCount = 1.5;
print('我有$appleCount斤苹果');
int intAppleCount = appleCount.toInt(); // double转int后直接去掉了小数部分
print(intAppleCount);
// num转double后赋值给double
appleCount = rest.toDouble(); // 进行转换后赋值
print(appleCount);

// double可以直接给num赋值
rest = appleCount;
print(rest);
}

布尔类型 bool

两个值: 真(true) 假(false)

使用 bool 关键字进行声明布尔值

实例:

1
2
3
4
5
6
7
8
void main() {
bool isCompleteHomeWork = false;
print('同学当前的作业状态是$isCompleteHomeWork');
isCompleteHomeWork = true;
print('同学当前的作业状态是$isCompleteHomeWork');

}

列表类型 List

使用List关键字进行列表声明

List中可存储任意数据类型

案例

1
2
3
4
5
6
7
8
9
void main() {
// 声明List
List students = ['张三', '李四', '王五'];

for (var element in students) {
print(element);
}
}

List的常用操作方法
  • 在尾部添加-add(内容)
  • 在尾部添加一个列表-addAll(列表)
  • 删除满足内容的第一个-remove(内容)
  • 删除最后一个-removeLast()
  • 删除索引范围内数据-removeRange(start,end) [范围内容包头不包尾]

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void main() {
List students = ['张三', '李四', '王五'];

// 添加内容
students.add('小明'); // 在尾部进行添加
print(students);

// 添加多个内容
students.addAll(['小红', '小兰', '喜羊羊']);
print(students);

// 删除满足内容的项
students.remove('喜羊羊');
print(students);

// 删除最后一个内容
students.removeLast();
print(students);

// 删除索引范围的列表内容(包头不包尾)
students.removeRange(0, 1);

// 循环查看
for (var element in students) {
print(element);
}
}

List列表中常用操作方法和属性
  • 循环-forEach((item){});
  • 是否都满足条件-eveny((item){return bool});
  • 筛选出满足条件的数据-where((item){return bool});
  • 列表长度(属性)-length
  • 最后一个元素(属性)-last
  • 第一个元素(属性)-first
  • 是否为空(属性)-isEmpty

where的返回值是可迭代对象,使用toList()方法可以转换为List类型

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void main() {
List students = ['张三', '李四', '王五', '新同学', '新同学2'];

students.forEach((item) {
print(item);
});

// 是否都是姓张的同学
bool isStartWithZhang = students.every((item) {
return item.toString().startsWith('张');
});
bool isStartWithZhang2 = students.every(
(item) => item.toString().startsWith('张'),
);
print('1.0是否都是姓张同学 ${isStartWithZhang}');
print('2.0是否都是姓张同学 ${isStartWithZhang2}');

// 根据条件筛选出对应数据的结果
List newStudentList = students.where((item) {
return item.toString().startsWith('新');
}).toList(); // 通过toList转换成List
print('新同学列表:');
print(newStudentList);

// 列表的长度
print(newStudentList.length);
// 打印列表最后一个
print(newStudentList.last);
// 打印列表第一个
print(newStudentList.first);
// 是否为空
print(newStudentList.isEmpty);
}

字典类型Map

需要存储键值对的时候要用到这个

使用Map关键字定义字典

语法和基本使用:

1
2
3
4
5
6
7
8
9
10
11
12
void main() {
Map transMap = {"lunch": "午饭", "morning": "早上", "hello": "你好"};
print(transMap);
// 取值
print(transMap['lunch']); // 午饭
// 设置值
transMap['car'] = "车";
print(transMap['car']); // 车
// 修改值
transMap['hello'] = '你非常好';
print(transMap['hello']);
}
字典常用方法
  • 循环遍历-forEach((item){})
  • 在添加一个字典-addAll(Map)
  • 是否包含某个key-containsKey(key值)
  • 删除某个key-remove(key值)
  • 清空-clear()

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void main() {
Map transMap = {"lunch": "午饭", "morning": "早上", "hello": "你好"};
print(transMap); // {lunch: 午饭, morning: 早上, hello: 你好}
// 取值
print(transMap['lunch']); // 午饭
// 设置值
transMap['car'] = "车";
print(transMap['car']); // 车
// 修改值
transMap['hello'] = '你非常好';
print(transMap['hello']); // 你非常好

Map transMap2 = {"eat": "吃", "fine": "非常好"};
// 添加一个字典
transMap.addAll(transMap2);
// 添加一个字典另一种写法(展开运算符)
transMap = {...transMap, ...transMap2};

print(
transMap,
); // {lunch: 午饭, morning: 早上, hello: 你非常好, car: 车, eat: 吃, fine: 非常好}

// 是否包含某个key
print('是否包含fine这个key:${transMap.containsKey('fine')}'); // 是否包含fine这个key:true

// 删除
transMap.remove('fine');
print(transMap); // {lunch: 午饭, morning: 早上, hello: 你非常好, car: 车, eat: 吃}

// 清空
transMap.clear();
print(transMap); // {}
}

动态类型dynamic

使用dynamic可以声明一个可变更类型的变量,可绕过编译检查

  • dynamic:运行时可自由改变类型,无编译检查,方法和属性直接调用
  • var:根据初始值进行推断,确定类型后,有编译检查,仅限推断的属性和方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void main() {
dynamic free = "字符串";
free = 1;
free = [];
free = false;
free = {};
free = "";
// 类型变化 不会引起编译的检查
// String text = "";
free.startsWith("");

var text = "10";
text.toString();
var a = "123";
}

0204dart中的空安全机制

类似于TypeScript中的空类型检测和控安全访问机制

操作符 符号 作用 实例
可空类型 ? 声明可空变量 String? 允许String或null
安全访问 ?. 对象为null时跳过操作,返回null user?.name 若user为null则返回nul
非空断言 !. 开发者保证变量非空(否则运行时崩溃) name!.length 断言name一定有length属性
空合并 ?? 左侧为null时返回右侧的默认值 name ?? “Guest” name为null时返回”Guest”
1
2
3
4
5
6
7
8
9
10
11
void main() {
String? username = null; // ? 标识变量可以是null
username?.startsWith("new"); // 安全访问
// 客观判断 username已赋值
// username = "张三";
// 主管判断-开发者认为username一定不为null
username!.startsWith("张"); // 非空断言

// 空合并
String displayName = username ?? 'User';
}

注意⚠️:在使用 !非空断言 的时候,一定要确保变量不为空

0205常见算数运算符

运算符 作用
+
-
*
/
~/ 整除
% 取余数

示例:

1
2
3
4
5
6
7
8
9
10
void main() {
var item = 10.99;
num allPrice = item * 4;
num money = 100;
num lastMoney = money - allPrice;
// 取整
int everyMoney = lastMoney ~/ 4;
print(everyMoney);
print(10 % 4);
}

0206常见赋值运算符

运算符 作用
= 赋值操作
+= 加等,a += b 相等于 a = a - b
-= 减等,a -= b 相等于 a = a - b
*= 乘等,a *= b 相等于 a = a * b
/= 除等,a /= b 相等于 a = a / b

示例:

1
2
3
4
5
6
7
8
9
10
11
12
void main() {
num a = 1;
a += 2; // 加等
print(a); // 3
a -= 1; // 碱等
print(a); // 2
a *= 3; // 乘等
print(a); // 6
a /= 2; // 除等
print(a); // 3.0
}

0207比较运算符

运算符 作用
== 判断两个值是否相等
!= 判断两个值是否不等
> 判断左侧值是否大于右侧值
>= 判断左侧值是否大于等于右侧值
< 判断左侧值是否小于右侧值
<= 判断左侧值是否小于等于右侧值

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void main() {
int a = 1;
int b = 2;
print(a == b); // false
print(a != b); // true
print(a > b); // false
print(a >= b); // false
print(a < b); // true
print(a <= b); // true

// 逻辑运算符
bool isOpenDoor = false; // 是否开门
bool isOpenLight = true; // 是否开灯

// 逻辑与
print(isOpenDoor && isOpenLight); // false
// 逻辑或
print(isOpenDoor || isOpenLight); // true

print(!isOpenDoor); // true
print(!isOpenLight); // false
}

0208常用逻辑运算符

运算符 作用
&& 逻辑与,a && b,a和b同时true,得true
|| 逻辑或,a||b,a和b有一个true,得true
! 逻辑非,!a,对a变量进行取反

示例:(见比较运算符的示例)

0209dart流程控制

  1. if分支语句
  2. 三元运算符
  3. switch/case
  4. 循环语句

if分支语句

单分支,单个条件判断

1
2
3
if(判断条件) {
...执行内容
}

双分支,两个条件判断

1
2
3
4
5
if(判断条件1) {
...执行内容
} else {
...执行内容2
}

多分支

1
2
3
4
5
6
7
8
9
10
int price = 80;
if(price >= 90) {
print("优秀")
} else if(price >= 80) {
print("良好")
} else if(price >= 60) {
print("及格")
} else {
print("不及格")
}

三元运算符

定义:在Dart语言中,三元运算符是一种简化版的双分支语句

语法:表达式 ? 结果1 : 结果2;

和JavaScript中的三元表达式一模一样

1
print( 59 >= 60 ? "及格" : "不及格")

在三元表达式中,不能写if、else了

switch/case多条件分支

分支条件很多,且条件判断相等,可以使用switch case语句

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
switch(变量){
case1:
逻辑1;
break;
case2:
逻辑2;
break;
case3:
逻辑3;
break;
defalut:
默认逻辑;
break;
}

0210循环

break关键字:跳出整段循环的关键字

continue关键字:跳过本次循环关键字

while循环

语法

1
2
3
while(循环条件){
...循环逻辑
}

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void main() {
// 列表
List foods = ["第一个包子", "第二个包子", "第三个包子", "第四个包子", "第五个包子"];
// 索引
int index = 0;
while (index < foods.length) {
print('吃 ${foods[index]}');
index += 1;
}

// 第一种场景 吃到第二个的时候就吃饱了 跳出整个循环使用break
index = 0;
while (index < foods.length) {
print('吃 ${foods[index]}');
if (index == 1) break; // 跳出整个循环
index += 1;
}

// 第二种场景 吃到第三个的时候 不吃第四个包子 吃第五个包子
index = 0;
while (index < foods.length) {
if (index == 3) { // 到第四个包子的时候
index += 1; // 下标加1
continue; // 并进行循环跳过,不吃第四个包子
}
print('吃 ${foods[index]}');
index += 1;
}
}

for循环

相比while循环,for循环有一定的条件结束

语法1:

1
2
3
for(初始化语句; 循环条件; 更新语句){
循环体逻辑
}

语法2:for-in (一般用于遍历列表、字典)

1
2
3
4
// item循环变量 list可迭代对象 in关键字
for (var item in list){
print(item)
}

语法1实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void main() {
// 列表
List foods = ["第一个包子", "第二个包子", "第三个包子", "第四个包子", "第五个包子"];
// 索引
for (int i = 0; i < foods.length; i++) {
print(foods[i]);
}

// 第一种场景 吃到第二个的时候就吃饱了 跳出整个循环使用break
for (int i = 0; i < foods.length; i++) {
print(foods[i]);
if (i == 1) break;
}

// 第二种场景 吃到第三个的时候 不吃第四个包子 吃第五个包子
for (int i = 0; i < foods.length; i++) {
print(foods[i]);
if (i == 2) continue;
}
}

03函数

将代码进行封装复用的工具,是 代码组合复用 的核心单元

使用场景:将运算方法进行封装,可以在很多需要用到的地方进行使用

函数中有几个概念:

  • 返回类型-return
  • 函数名-name
  • 参数-(arg1,arg2)
  • 函数体-{..}

函数基本单元:

1
2
3
4
// 函数名add 函数返回值类型int
int add (int a, int b) {
return a + b;
}

使用示例:

1
2
3
4
5
6
7
8
9
void main() {
// 使用
print(add(2, 4)); // 6
}

// 声明
int add(int a, int b) {
return a + b;
}

函数返回值

分类:函数分为有 返回值没有返回值

  • 有返回值:具体类型 函数名称() {}
  • 无返回值:void 函数名称() {}

注意⚠️:返回值类型可省略,Dart将会自动推断类型为dynamic

示例:

1
2
3
add(int a, int b) { // 此时函数类型推断为dynamic
return a + b;
}

函数参数

可选位置参数

特点:可选位置参数必须位于必传参数后面,采用中括号包裹

语法:函数名(String a,[String? b ...]),传递时按照顺序传递

使用场景:参数少且顺序固定

示例:

1
2
3
4
5
6
7
8
void main() {
print(combine("1"));
}

// 参数为可选参数时需要用[]进行包裹,并且参数类型后边需要跟上?号表示可选参数
String combine(String a, [String? b, String? c]) {
return a + (b ?? "") + (c ?? "");
}
参数默认值

参数默认值一般与可选位置参数进行搭配使用,因为必填参数是一定有值传入的,但是可选位置参数则可以设置默认值

语法:函数名([String? a = "a"]){}

1
2
3
4
5
6
7
8
9
void main() {
print(combine("1"));
}

// 参数为可选参数时需要用[]进行包裹,并且参数类型后边需要跟上?号表示可选参数
// 在参数后边通过 = 默认值 可设置参数的默认值
String combine(String a, [String? b = 'b', String? c = 'c']) {
return a + (b ?? "") + (c ?? "");
}
可选命名参数

特点:可选命名参数必须位于必传参数后面,采用 大括号 包裹

语法:函数名(String a,{string? b,...}) ,传递时按照 参数名:值 的方式进行传递,无需关注顺序

使用场景:参数多且需明确含义时

类似于TypeScript中参数为对象且对象中的属性为可选属性的情况

示例:

1
2
3
4
5
6
7
8
9
10
void main() {
// 在调用函数进行传参时,命名参数不需要在意顺序
showPerson('小明',age: 25,sex: '男'); // 姓名:小明,年龄:25,性别:男
}

// 可选命名参数,使用大括号{}包裹,参数类型后边也需要跟?号表示可选参数
// 在参数后边通过 = 默认值 可设置参数的默认值
void showPerson(String username, {int? age = 18, String? sex = '女'}) {
print('姓名:${username},年龄:${age},性别:${sex}');
}

匿名函数

特点:可以声明一个没有名称的函数赋值给变量,进行调用

语法:Function 变量名 = () {};

注意⚠️:函数的类型使用Function来声明

其实应该叫函数声明式:

1
Function test = () {}

但是后边的() {}就是一个匿名函数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
void main() {
test("给力");
onTest(test);
}

Function test = ([String? a = "test"]) {
print('测试数据:${a}');
};

void onTest(Function callback) {
callback();
}

箭头函数

特点:当函数体只有一行代码时,可以使用箭头函数编写

语法:函数名()=>代码逻辑

注意⚠️:使用箭头函数可以省略 return 关键字

示例:

1
int add(int a,int b) => a + b;

评论