Dart语言学习
Dart介绍
Dart是由谷歌开发的计算机编程语言,它可以被用于web、服务器、移动应用和物联网等领域的开发。
Dart诞生于2011年,号称要取代JavaScript。但是过去的几年中一直不温不火。直到Flutter的出现现在被人们重新重视
要学Flutter的话我们必须首先得会Dart.
Dart开发环境配置
安装Dart
在使用Dart开发之前,首先要配置Dart开发环境,我们在官网可以找到在windows和mac上安装Dart SDK的方法,也可以在dart for windows 中使用 .exe
文件进行安装

下载后,双击执行,选择好安装位置后,一路next,安装程序会默认把dart添加进环境变量的,输入dart --version
出现下图表示安装成功

vscode中配置开发Dart
在 vscode 中安装dart插件
在 vscode 中安装 code runner 来运行我们的代码
测试运行
新建一个 myfirst.dart
文件,输入以下代码,运行
1 | main() { |


Dart 学习
基本语法
dart
和 C
语言有点类似,每句话结束需要使用 ‘;’,注释也与 C
类似,使用 //
/**/
来进行注释
Dart 的入口方法
1 | // dart的入口方法 |
Dart 中的变量
dart 是一个脚本类语言,可以不预先定义变量类型,自动会进行类型推断,这一点和 javascript
有点相似
1 | var str = "this is var"; |
也可以通过类型来申明变量
1 | String str = 'this is var'; |
注意:
- 变量名称必须由数字、字母、下划线、美元符($)组成
- 标识符开头不能是数字
- 标识符不能是保留字和关键字
- 变量的名字是区分大小写的
- 标识符一般要见名思意
Dart中的数据类型
数值型:
- int
- double
字符串:
String
1
2
3
4
5
6
7String str1 = 'sdfsdf';
String str2 = "sfsdfsf";
// 可以用三个单引号来定义多行字符串
String str3 = '''sdfsdfssdf
sdfsdfsdf
sdfsdf
'''字符串的拼接
1
2
3
4String str1 = "yjr";
String str2 = "1100";
print("$str1$str2");
print(str1 + str2);
布尔:
- bool
1
2bool flag = true;
bool flag2 = false;
- bool
List:
- 在Dart中,数组是列表对象,所以大多数人只称它们为列表
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
35
36
37
38
39
40
41
42
43
44
45// 定义List
var list1 = ["sdf",123,true];
print(list1);
//获取集合的长度
print(list1.length)
// 通过索引可以获取数据
print(list1[0]);
print(list1[1]);
print(list1[2]);
// 定义指定类型的 List
var list2 = <String>["sdf","kkk"];
var list3 = <int>[12,34];
// 定义空的 List,动态的向其中添加数据
var list4 = [];
list4.add("sdf");
// 老版本的Dart还可以通过new的方式来创建list,不过新版本已经不用了
var list5 = new List();
// 创建一个固定长度的集合,不可增加数据,但是可以修改里面的数据,不可以修改长度
var list6 = List.filled(3,"");
var list6 = List<String>.filled(3,"");
// 除了使用var,还可以用List 来声明数据类型
List list7 = [12,34,56];
// List 常用属性
print(list7.length); // 返回list长度
print(list7.reversed); // 翻转list,返回的不是list,用 toList()方法来转成list
print(list7.isEmpty); // 判断list是否为空
print(list7.isNotEmpty); // 判断list是否非空
// List 常用方法
list7.add(55); //增加一个数据
list7.addAll([12,34,46,99]); //一次增加多个数据
list7.indexOf(12); //查找索引,如果查不到返回-1,否则返回找到的第一个索引位置
list7.remove(34); // 删除 34 这个值,如果有多个,删除前面的
list7.removeAt(0); // 删除0号位置的元素
list7.fillRange(1,2,888); // 修改位置1开始到位置2(不包括位置2)的元素值为888
list7.insert(1,777); // 在1号位置之前插入777 这个值
list7.insertAll(1,[333,4444]); // 一次插入多个值
var str = list7.join(",");// 把list转为字符串,用逗号分隔
str.split(","); //把字符串转为list,用逗号切割
- 在Dart中,数组是列表对象,所以大多数人只称它们为列表
Set:
和list差不多,就是不能有重复的数据,下面主要看一下怎么定义一个set
。1
2
3
4
5
6var set1 = {12,34,12};
print(set1); // 重复的数据没有
var set2 = new Set();
set2.add(34);
set2.addAll([2,3,12,34]);Map:
通常来说,Map
是一个键值对相关的对象,键和值可以是任何类型的对象,每个键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// 定义一个Map
var person ={
"name":"yjr1100",
"age":12
};
// 另一种方法定义一个Map
var p = new Map();
p["name"] = "yjr1100";
p["age"] = 12;
// Map的常用属性
print(person.keys); // 获取所有的key
print(person.values);// 获取所有的 value
print(person.isEmpty); // 判空
print(person.isNotEmpty); // 判非空
// Map的常用方法
person.addAll({
"work":"打代码",
"height":100
}); // 添加键值对
person.remove("work"); //删除属性
person.containsValue("yjr1100"); // 看所有值中有没有 “yjr1100” 这个value
person.containsKey("name"); // 看看所有的key中有没有 name这个keyList Map 和 Set 的遍历
下面用list做演示,其它几种用法类似1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17List list1 = [12,34,87,24343,34];
for(int i = 0;i<list1.length;i++){
print(list[i]);
}
for(var item in list1){
print(item);
}
list1.forEach((value){
print(value);
})
var newlist = list1.map((value)=>value*2);// 可以用来修改每个值
var newlist2 = list1.where((value) => value>20); // 把满足条件的元素组成新的list返回
var f = list1.any((value) => value>30); // 只要集合里有一个满足条件,就返回true
var f2 = list1.every((value) => value>30); // 只要集合里元素都条件,就返回true
类型的判断
1 |
|
类型的转换
Number 和 String 类型之间的转换
1
2
3
4
5
6// Number转String toString();
var myNum = 12;
var str1 = myNum.toString();
// String转Number parse;
String str="123";
var mynum = int.parse(str);其它类型和boolean类型的转换
1
2
3
4
5
6
7
8
9
10
11var str = "123";
str.isEmpty
var myNum = 0;
myNum==0;
var a;
a == null;
var b = 0/0;
b.isNaN
final 和 const修饰符
const 值不变,开始就要赋值
final 可以开始不赋值,只能赋值一次
final 和 const的主要区别:final不仅有const编译时常量的特性,最重要的是它是运行时常量,是惰性初始化,即在运行时第一次使用前才初始化
Dart 中的运算符
算术运算符
+
、-
、 *
、/
、 ~/
(取整)、%
(取余)、++
、--
关系运算符
==
、 !=
、 >
、 <
、 >=
、 <=
逻辑运算符
!
、 &&
、 ||
赋值运算符
基础赋值运算符
=
、??=
1
2
3
4
5
6int b = 10;
b??=23; //b是空的时候,把23赋值给b
print(b);
var c;
c??=99; //如果c是空的时候,把99赋给c
print(c);复合赋值运算符
+=
、-=
、*=
、/=
、%=
、~/=
Dart 中的流程控制
条件表达式
- if-else
- switch-case
1
2
3
4
5
6
7
8
9
10
11
12var sex = "男";
switch(sex){
case "男":
print("是男的");
break;
case "女":
print("是女的");
break;
default:
print("都不是");
break;
} - 三目运算符
- ??运算符
1
2
3var a;
var b = a ?? 10;
print(b) //如果a是空的时候,把 10 赋值给b
for循环
和c++
相同
1 | for(int i = 0;i<50;i++){ |
while循环
1 | int i = 1; |
break 和 continue
break语句功能:
- 在switch语句中使流程跳出switch结构。
- 在循环语句中使流程跳出当前循环,遇到break循环终止,后面代码也不会执行
强调:
- 如果在循环中已经执行了break语句,就不会执行循环体中位于break后的语句。
- 在多层循环中,一个break语句只能向外跳出一层
break可以用在switch case中也可以用在for循环和while循环中
continue语句的功能:
- 只能在循环语句中使用,使本次循环结束,即跳过循环体重下面尚未执行的语句,接着进行下次循环,continue可以用在for循环以及while循环中,但是不建议用在whi1e循环中,不小心容易死循环
Dart 中的函数
自定义方法
这里和C++
语言类似,代码如下。
1 | // 基本格式 |
箭头函数
箭头函数里的代码就只有一行
1 | List list1=[1,2,3]; |
匿名函数
就是没有名字的函数,一般来说就是临时用的时候写一下,在下面的代码中,括号就是用来传参的参数列表,后面是函数体,我们将这个没有名字的函数赋值给了printNum,就可以通过printNum来调用它;
1 | var printNum = (int n){ |
对于匿名方法,我们有自动执行的方式,就是不需要显示的调用,直接让它自己自动执行,并且也可以传入参数
1 | ((n){ |
函数的闭包
- 全局变量:全局变量常驻内存、全局变量污染全局
- 局部变量:不常驻内存,会被垃圾回收机制回收,不会污染全局
引入闭包:
- 常驻内存
- 不污染全局
闭包粗浅的理解就是函数内部嵌套函数,内部函数会调用外部函数的变量或参数,变量或参数不会被系统回收
1 | fn(){ |
Dart 中的类
面向对象编程(O0P)的三个基本特征是:封装、继承、多态
封装:封装是对象和类概念的主要特性。封装,把客观事物封装成抽象的类,并且把自己的部分属性和方法提供给其它函数使用。
继承:面向对象编程(O0P)语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的功能,并有它父类的功能。
多态:允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果。
Dart所有的东西都是对象,所有的对象都继承自Object类。
Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类
一个类通常由属性和方法组成。
定义一个类
1 |
|
dart没有像 C++
那样使用 public,private,protected 等修饰符来限制类属性的访问权限,如果我们想要把一个方法或者属性定义为私有,需要在定义时名字前面 加上 _
,而且私有方法和私有属性必须单独放在一个文件中。
dart中的getter,setter
在dart中通过 get
可以让一个方法像类属性那样直接使用
1 | class Rect{ |
Dart中的静态成员
可以通过 static
关键字来实现类级别的变量和函数,即不需要实例化对象,就可以使用
静态方法不能访问非静态成员,静态方法可以访问静态成员,非静态方法可以访问静态成员以及非静态成员。在类里,我们一般使用this访问非静态属性,而直接用属性名访问静态属性。
1 | class Person{ |
Dart中的对象操作符
?
条件运算符as
类型转换is
类型判断..
级联操作
1 | Person p; |
Dar类的继承
子类使用 extends
关键字来继承父类
子类会继承父类里面可见的属性和方 但不会继承构造函数
子类能复写父类的方法 getter 和 setter
1 | class Person{ |
抽象类
Dart中抽象类:Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
- 抽象类通过
abstract
关键字来定义 - Dart中的抽象方法不能用
abstract
声明,Dart中没有方法体的方法我们称为抽象方法。 - 如果子类继承抽象类必须得实现里面的抽象方法
- 抽象类不能被实例化,只有继承它的子类可以
- 如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
1 | abstract class Animal{ |
Dart中的接口
和Java一样,dart也有接口,但是和Java还是有区别的。
首先,dart的接口没有interface
关键产定义接口,而是普通类或抽象类都可以作为接口被实现。建议使用抽象类定义接口,实现接口,必须重写抽象类中的所有属性和方法。
使用implements
:关键字进行接口实现。
extends
抽象类和implements
的区别:
- 如果要复用抽象类里面的其它普通方法,并且要用抽象方法约束子类的话我们就用extends继承抽象类
- 如果只是把抽象类当做标准的话我们就用implements:实现抽象类
1 | abstract class Db{//当做接口接口:就是约定、规范 |
Dart中可以一个类实现多个接口,我们需要实现所有接口中的所有属性和方法。
1 | abstract class A{ |
Dart中的mixins
mixins的中文意思是混入,就是在类中混入其他功能。在Dart中可以使用mixins实现类似多继承的功能
因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:
- 作为mixins的类只能继承自object,不能继承其他类
- 作为mixins的类不能有构造函数
- 一个类可以mixins多个mixins类
- mixins绝不是继承,也不是接口,而是一种全新的特性
1 | class A{ |
Dart中的多态
允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果
子类的实例赋值给父类的引用。
多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
1 | abstract class Animal{ |
Dart中的泛型
泛型就是解决类、接口方法的复用性、以及对不特定数据类型的支持(类型校验)
1 | T getData<T>(T value){ |
Dart 中的库
Dart中的库主要有三种:
我们自定义的库
1
import 'lib/xxx.dart';
系统内置库
1
2
3import 'dart:math';
import 'dart:io';
import 'dart:convert';Pub包管理系统中的库
在下面的网站中,我们就可以找到一些第三方库进行下载
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
使用时:
- 需要在自己项目根目录新建一个
pubspec.yam1
- 在
pubspec.yaml
文件然后配置名称、描述、依赖等信息1
2
3
4name:XXX
description:A new flutter module project.
dependencies:
http:^8.12.0+2 - 然后在项目目录中运行pub get获取包下载到本地
- 项目中引入库
import'package:http/http.dart'as http;
看文档使用
如果有库冲突,我们可以使用 as
来重命名库,通过 show
关键字,可以进行库的部分引入,即只引入我们需要的部分。通过hide
关键字,可以隐藏库中的某些部分,而引入其它部分。
Dart 2.13 以后的一些新特性
Null safety
空安全,可以帮助开发者避免一些日常开发中很难被发现的错误,并且额外的好处是可以改善性能
Flutter2.2.0(2021.5.19发布)以后的版本都要求使用 Null Safety
?
使用问号,表示可空类型1
2
3
4
5
6
7
8
9
10// int a = 12;
// a = null; 不可以赋值为null,报错
int? a = 12;
a = null; //可以 ,int? 表示 a 可以是空类型
String? getDate(url){
if(url==null){
return null;
}
}!
类型断言1
2
3
4String? str="sdfsdfsdf";
str = null;
//print(str.length);// 报错,因为str是可空类型,我们需要进行类型断言
print(str!.length) //类型断言,如果不等于null,打印长度,如果是null,抛出异常required 关键词
最开始 @required
是注释,现在它已经作为内置修饰符,主要用于标记命名参数,使得他们不为空。
1 |
|
const 和final补充
core库中 identical 函数的用法
通过 identical
函数,可以检查两个引用是否指向同一个对象
1 | var o1 = new Object(); |
常量构造函数
1 | //常量构造函数 |
常量构造函数总结如下几点:
- 常量构造函数需以
const
关键字修怖 - const构造函数必须用于成员变量都是
final
的类 - 如果实例化时不加cost修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
- 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象
- Flutter中
const
修饰不仅仅是节省组件构建时的内存开销,Flutter在需要重新构建组的时候,不构建const
声明的组件。