AS创建空的Dart工程
// 查看Dart SDK版本
$ dart --version
Dart SDK version: 2.13.4 (stable) (Wed Jun 23 13:08:41 2021 +0200) on "macos_x64"
// 查看Dart SDK安装的地方,发现是在flutter SDK包里边
$ which dart
/Users/wn/Documents/flutter/bin/dart
AS创建Dart空工程
-
Android Studio
->New Flutter Project
配置工程名
- 新建
Modules
- 给
Module
命名
创建好的Dart
空工程
var 、final和const
新建flutter
工程dart_demo1
,工程类型为Application
- 变量
var
的使用
void main() {
// 声明一个变量a
var a;
print(a);
a = 'hello world';
print(a);
a = 10;
print(a + 10);
// 变量也可以在声明的时候直接赋值
var b = 666;
print(b);
}
// 打印内容
null
hello world
20
666
使用var
声明一个变量,可以赋值不同的类型;var声明的变量如果没有初始化,那么它的值为null
;变量也可以在声明的时候直接赋值。
- 最终变量
final
的使用
// 案例一
void main() {
final c = 999;
c = 'hello';
}
// 最终变量c不能被再次赋值
lib/main.dart:17:3: Error: Can't assign to the final variable 'c'.
c = 'hello';
^
// 案例二
final d;
print(d);
// 最终变量d在使用之前必须赋值,
// final声明的变量,如果没有赋值,是不能使用的
lib/main.dart:24:9: Error: Final variable 'd' must be assigned before it can be used.
print(d);
^
// 案例三
final c;
c = 10;
print(c);
// 打印内容
10
- 常量
const
的使用
// 常量声明的时候就必须赋值,常量也是不能修改的
const e = 10;
print(e);
// 打印内容
10
Dart的数据类型-num
num
类型有两种int
与double
// 案例一
void numDemo() {
num a;
print(a);
}
// num类型在使用之前必须赋值
lib/main.dart:6:9: Error: Non-nullable variable 'a' must be assigned before it can be used.
print(a);
^
// 案例二
void numDemo() {
num a = 10;
print(a);
a = 1.5;
print(a);
}
// 打印内容
10
1.5
// 案例三
int a = 10;
print(a);
a = 1.5;
print(a);
// int类型是不能被赋值为double类型的数值
lib/main.dart:7:7: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
a = 1.5;
^
// 案例四
// double类型可以被赋值为int类型的数值
double a;
a = 10;
print(a);
// 打印内容
10
// 案例五
int a = 8;
print(a.isEven);//判断是否为偶数
print(a.isOdd);//判断是否为奇数
// 打印内容
true
false
// 案例六
// 算数运算符: + - * / %(取模) ~/(两数相除取整)
double a = 10;
int b = 8;
print(a ~/ b);
// 类型转换
print(a.toInt().isEven);
print(b.toDouble());
// 打印内容
1
true
8
Dart的数据类型-String
字符串使用单引号''
和双引号""
创建
// 案例一
void stringDemo() {
var a = 'a';
var b = 'b';
print(a + b);
}
// 打印内容
ab
// 案例二
var b = 'b';
b = 10;
// int类型不能被赋值到String类型中
lib/main.dart:6:7: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
b = 10;
^
// 案例三
var a = 'a';
var b;
b = 'b';
b = 10;
print(a + b);
// String类型与int类型不能拼接
Error: Expected a value of type 'String', but got one of type 'int'
// 案例四
// 三个引号或双引号可以创建多行字符串
String str = 'abc';
print(str);
String str2 = "d"
"e"
"f"; //实际上是拼接在一起,为def
print(str2);
// 打印内容
abc
def
// 使用转义字符是字符串换行
String str2 = "d\n"
"e\n"
"f";
// 打印内容
d
e
f
// 案例五
// 三个引号不仅是换行,而且把回撤也保留了
String str2 = '''d
e
f''';
print(str2);
// 打印内容
d
e
f
// 案例六
// 可以像数组一样取字符串中的第几个字符
String str = 'abc';
print(str[0]);
print(str[1]);
// 打印内容
a
b
// 案例七
// 字符串也可以乘以数字,相当于对字符串复制几份
String str = 'abc';
print(str * 2);
// 打印内容
abcabc
// 案例八
// 使用{}来存放表达式
int a = 10;
int b = 20;
print('a + b = ${a + b}');
// 打印内容
a + b = 30
// 使用变量$c表示计算结果,没有表达式就不需要{}
int a = 10;
int b = 20;
int c = a + b;
print('a + b = $c');
// 打印内容
a + b = 30
// 案例九
// 使用r来打印转义字符
String str = 'abc\n123';
String str1 = r"abc\n123";
print(str);
print(str.length);
print(str1);
print(str1.length); //打印字符串长度
// 打印内容
abc
123
7 // 转义字符是一个字符,相当于return
abc\n123
8
Dart的数据类型list&Map
- list数组的使用,数组分为
可变数组
与不可变数组
// 案例一
void listDemo() {
// 数组中可以存放不同的数据类型
// 创建可变数组list1
var list1 = [1,2,3,'abc'];
print(list1);
// 获取数组中不同脚标对应的数据
print(list1[3]);
list1[3] = '123';
print(list1);
}
// 打印内容
[1, 2, 3, abc]
abc
[1, 2, 3, 123]
// 案例二
// 创建不可变数组list1
var list1 = const [1,2,3,'abc'];
print(list1);
print(list1[3]);
list1[3] = '123';
print(list1);
// 不可变数组不能对元素进行赋值
Error: Unsupported operation: indexed set
// 案例三
// 可变数组的添加、插入、删除、清空操作
var list1 = [1,'abc'];
list1.add(2);
print(list1);
list1.insert(1, 3);
print(list1);
list1.remove(1);
print(list1);
list1.clear();
print(list1);
// 打印内容
[1, abc, 2]
[1, 3, abc, 2]
[3, abc, 2]
[]
// 案例四
// 可变数组的排序和截取
var list1 = [1,3,5,2,4,9,8,6];
list1.sort();
print(list1);
// 从脚标4开始到脚标7,注意不包含7,[4 7)
print(list1.sublist(4,7));
// 打印内容
[1, 2, 3, 4, 5, 6, 8, 9]
[5, 6, 8]
- Map字典的使用,字典分为
可变字典
与不可变字典
// 案例一
void mapDemo() {
// 创建可变map
var json1 = {'one': 1, 'two': 2};
print(json1);
print(json1['one']); //取值
json1['one'] = 3; //赋值
print(json1);
}
// 打印内容
{one: 1, two: 2}
1
{one: 3, two: 2}
// 案例二
// 创建不可变map
var json1 = const {'one': 1, 'two': 2};
json1['one'] = 3; //赋值
// 不可变map不能被赋值
Error: Unsupported operation: Cannot modify unmodifiable map
// 案例三
// 获取字典的keys 、values 、length
var json1 = {'one': 1, 'two': 2};
print(json1.length);
print(json1.keys);
print(json1.values);
// 打印内容
2
(one, two)
(1, 2)
// 案例四
// 数组转map
var list = ['a', 'b', 'c'];
print(list.asMap());
// 打印内容
{0: a, 1: b, 2: c}
Dart的运算符
- 赋值运算符
??=
void operatorDemo() {
var a;
a ??= 10; //如果a为null就赋值,如果有值就直接返回
a ??= 5;
a ??= 1;
print(a);
}
// 打印内容
10
如果a为null
就赋值,如果有值就直接返回。
- 条件表达式
??
var b;
print(b ?? 1);
// 打印内容
1
var b;
b = 5;
print(b ?? 1);
// 打印内容
5
如果b
有值就返回b
,否则就返回1
。
Dart中的方法&箭头函数
Dart
中的方法也是一个对象,返回值和参数类型可以省略;当方法的执行语句只有一句的时候,可以使用箭头函数 => 表达式
。
- 箭头函数
// 可以把方法的调用作为一个执行语句
void main() => functionDemo();
void functionDemo() => print('function');
- 省略方法的
返回值
和参数类型
void functionDemo() {
print(sum(10, 20));
}
sum(a, b) {
return a + b;
}
// 把sum方法简化成箭头函数
sum(a, b) => a + b;
// 把sum箭头函数修改为三目运算符类型
sum(a, b) => a == 1 ? a + b : a - b;
注意:不推荐省略方法的返回值
和参数类型
。
Dart方法的可选参数
可选参数:传递参数的时候必须带上形参的名字
(否则不知道是哪个参数)
// 案例一
void functionDemo() {
// 可选参数可以不按顺序传递
print(sum1(1,c: 2,b: 3));
// 只传两个参数
print(sum1(1,b: 3));
}
sum1(int a, {b, c}) {
b ??= 0;
c ??= 0;
return a + b + c;
}
// 打印内容
6
4
// 案例二
// 可选参数类型改为int
sum1(int a, {int b, int c}) {
b ??= 0;
c ??= 0;
return a + b + c;
}
// 报错提示int类型不能为空
Try adding either an explicit non-'null' default value or the 'required' modifier.
sum1(int a, {int b, int c}) {
^
lib/main.dart:9:3: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
b ??= 0;
^
lib/main.dart:10:3: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
c ??= 0;
^
// 解决方法一:nullability
// int? 告诉编译器,处理了后面为空的情况
sum1(int a, {int? b, int? c}) {
b ??= 0;
c ??= 0;
return a + b + c;
}
// 解决方法二:可选参数给默认值
sum1(int a, {int b = 0, int c = 0}) {
return a + b + c;
}
// 案例三
sum1(int a, {int b = a, int c = a}) {
return a + b + c;
}
// 找不到参数a
Waiting for connection from debug service on Chrome...
lib/main.dart:8:22: Error: Getter not found: 'a'.
sum1(int a, {int b = a, int c = a}) {
^
lib/main.dart:8:33: Error: Getter not found: 'a'.
sum1(int a, {int b = a, int c = a}) {
^
// 案例四:传递的可选参数是有顺序的
void functionDemo() {
print(sum2(1, 2, 3));
// 参数b的值为3,不能跳过参数b给参数c传值
print(sum2(1, 3));
}
sum2(int a, [int b = 0, int c = 0]) {
return a + b + c;
}
// 打印内容
6
4
Dart方法作为参数传递
方法也是对象:使用场景作为参数传递
。
// 案例一
void functionDemo() {
// Dart的方法也是一个对象
var hello = printHello;
hello();
}
printHello() => print('hello');
// 打印内容
hello
// 案例二
void functionDemo() {
var list = [1, 2, 3, 4];
list.forEach(print);
}
// 打印内容
1
2
3
4
// 查看forEach源码:遍历list数组,把数组内的元素当作方法f的参数
void forEach(void f(E element)) {
for (E element in this) f(element);
}
// 案例三:使用自定义forEach方法和自定义print方法
void functionDemo() {
var list = [1, 2, 3, 4];
forEachDemo(list, printElement);
}
forEachDemo(List list, void func(var element)) {
for (var e in list) func(e);
}
int b = 0;
printElement(var a) {
b++;
print('元素$b = $a');
}
// 打印内容
元素1 = 1
元素2 = 2
元素3 = 3
元素4 = 4
Dart中的匿名函数
匿名函数:没有方法名称的方法
。
// 案例一
void functionDemo() {
// 匿名函数赋值,保留其地址来调用
var func = (){
print('匿名函数');
};
func();
}
// 打印内容
匿名函数
// 案例二
void functionDemo() {
// 立即执行的匿名函数
((){
print('立即执行函数');
})();
}
// 打印内容
立即执行函数
// 案例三
void functionDemo() {
var list = [1, 2, 3, 4];
int b = 0;
// 函数式编程,类似于OC的block
// 匿名函数作为参数的实战
// 这里的匿名函数与闭包还是有区别的,闭包是定义在函数内部的函数
forEachDemo(list, (var a) {
b++;
print('元素$b = $a');
});
}
forEachDemo(List list, void func(var element)) {
for (var e in list) func(e);
}
// 打印内容
元素1 = 1
元素2 = 2
元素3 = 3
元素4 = 4
Dart中的闭包
闭包的概念
:定义在函数内部的函数,闭包也是一个对象;
闭包的作用
:可以访问外部函数的局部变量;闭包就是一个闭环,让内部函数可以持续访问外部函数。
// 案例一
void closureDemo() {
var func = funcA();
func();
func();
func();
func();
}
funcA() {
int count = 0;
return () => print(count++); //这个匿名函数就是一个闭包
}
// 打印内容
0
1
2
3
由打印内容说明count
一直在内存中,并没有释放,这就是闭包的典型作用;funcA
函数执行完毕,只要我们获取到funcA
函数返回的闭包,那么funcA
函数中的变量就会一直存在,不会释放。
// 案例二
void closureDemo() {
var func = funcA();
func();
func();
func();
func();
var func2 = funcA();
func2();
func2();
func2();
func2();
}
// 打印内容
0
1
2
3
0
1
2
3
func2
获取的是一个新的闭包对象,所以count
就是一个全新的栈内存。