文章目录
知识回顾
前言
源码分析
1. 变量、常量
常量:
- 声明变量:var 变量名 = 表达式;
- 修改变量:变量名 = 新值;
- 类型推断:var关键字声明的变量支持类型推断,修改变量时会检查之前存储数据的类型
变量:
- 需求:存储不可被修改的数据
- 实现:常量关键字:const 和 final
- 区别:final是运行时常量,值在运行时赋值;const是编译期常量,值在编译时赋值;
注意: const 和 final的区别
final:运行时常量,值在运行时赋值
const:编译期常量,值在编译时赋值
2. 数据类型 num string bool List Map
num String bool
num类型的变量既可以存整数也可以存小数
int类型的值可以赋值给double类型的变量,但是double类型的值不能赋值给int类型的变量
void main() {
// 1. num类型 (整数、小数)
num n1 = 10;
print(n1); // 10
n1 = 10.1;
print(n1); // 10.1
// 2. int类型 (整数)
int n2 = 20;
print(n2); // 20
// 测试:将小数赋值给int
// 报错:A value of type 'double' can't be assigned to a variable of type 'int'.
// n2 = 20.2;
// 3. double类型 (小数)
double n3 = 30.3;
print(n3); // 30.3
// 测试:将整数赋值给double
n3 = 30;
print(n3); // 30.0
}
List
需求:使用一个变量有序的存储多个值
实现:列表(数组)关键字:List
● 定义列表 List 变量名 = [元素1, 元素2, ..., 元素n];
○ 1.1 需求:按序存储数字 1 3 5 7
○ 1.2 需求:按序存储字符串 '居家' '美食' '服饰'
○ 1.3 列表中可以存储任意类型的数据
void main() {
// 1. 定义列表:List 变量名 = [元素1, 元素2, ..., 元素n];
// 1.1 需求:按序存储数字 1 3 5 7
List nums = [1, 3, 5, 7];
print(nums);
// 1.2 需求:按序存储字符串 '居家' '美食' '服饰'
List categories = ['居家', '美食', '服饰'];
print(categories);
// 1.3 列表中可以存储任意类型的数据
List ret = [
18,
18.8,
'美食',
true,
['', 10],
{}
];
print(ret);
}
3. 综合
void main() {
// 准备购物车数据
List carts = [
{"count": 2, "price": 10.0, "selected": true},
{"count": 1, "price": 30.0, "selected": false},
{"count": 5, "price": 20.0, "selected": true}
];
// 记录总金额
double totalAmount = 0.0;
// 遍历购物车数据
carts.forEach((element) {
// 读取商品的勾选状态
bool selected = element['selected'];
// 如果商品被勾选 ,读取该商品的单价和数量,并计算价格小计
if (selected) {
double amount = element['count'] * element['price'];
// 累加价格小计,计算总价
totalAmount += amount;
}
});
print(totalAmount);
}
4. 函数
void main() {
// 2. 调用无参数无返回值函数
func();
// 4.调用有参数有返回值函数
int ret = sum(10, 20);
print(ret); // 30
}
// 1. 定义函数:无参数无返回值函数
void func() {
print('这是一个无参数无返回值函数');
}
// 3. 定义函数:有参数有返回值函数
// 需求:定义函数,计算任意两个整数的和,并返回计算结果
int sum(int a, int b) {
int ret = a + b;
return ret;
}
void main() {
// 1.2 定义一个变量接收函数
// var f = funcDemo1;
Function f = funcDemo1;
f();
// 2.2 函数作为参数
funcDemo2(funcDemo3);
}
// 1.1 函数可以作为对象赋值给其他变量
void funcDemo1() {
print('funcDemo1');
}
// 2.1 函数可以作为参数传递给其他函数
void funcDemo2(Function func) {
// 调用外界传入的函数
func();
}
// 定义作为参数的函数: 把funcDemo3传入到funcDemo2
void funcDemo3() {
print('funcDemo3');
}
匿名函数
void main() {
// 匿名函数
// 1. 匿名函数赋值给变量,并调用
Function f = () {
print('这是一个匿名函数');
};
f();
// 2. 可以作为参数传递给其他函数去调用(回调函数)
funcDemo(() {
print('这个匿名函数是个参数');
});
}
// 定义一个接收函数作为参数的函数
void funcDemo(Function func) {
func();
}
箭头函数
void main() {
int ret1 = sum1(10, 20);
print(ret1);
int ret2 = sum2(30, 40);
print(ret2);
}
// 思考:以下代码可以简写吗?
sum1(a, b) {
return a + b; // 函数体只有一行代码
}
// 箭头函数简写函数体:简写只有一行代码的函数体
sum2(a, b) => a + b;
综合
void main() {
// 准备购物车数据
List carts = [
{"count": 2, "price": 10.0, "selected": true},
{"count": 1, "price": 30.0, "selected": false},
{"count": 5, "price": 20.0, "selected": true}
];
// 调用封装的函数
bool isSelectedAll = getSelectedState(carts);
if (isSelectedAll) {
print('全选');
} else {
print('非全选');
}
}
// 核心逻辑:只要有任何一个商品是未勾选的,那么就是非全选
bool getSelectedState(List carts) {
// 购物车初始的状态:假设默认是全选
bool isSelectedAll = true;
carts.forEach((element) {
bool selected = element['selected'];
// 核心代码:只要有任何一个商品是非勾选的,则购物车就是非全选
if (selected == false) {
isSelectedAll = selected;
}
});
// 返回是否全选结果
return isSelectedAll;
}
5. 类
6. 异步
import 'dart:io';
void main() {
print('开始执行主线程--同步');
getNetData().then((res) {
print(res);
}).catchError((error) {
print(error);
});
print('会被阻塞吗???');
}
Future<String> getNetData() {
return Future(() {
sleep(Duration(seconds: 5));
// return '成功获取网络数据';
throw Exception('异步线程中错误');
});
}
7. 示例
// 用户先登录,登录成功之后拿到token,然后再保存token到本地
import 'dart:io';
void main() {
print('启动');
login().then((token) {
setToken(token).then((res) {});
}).catchError((e) {});
print('结束');
}
// 登录
Future<String> login() {
return Future(() {
sleep(Duration(seconds: 2));
print('登录成功');
// 返回token
return '111111';
});
}
// 存储token
Future<bool> setToken(String token) {
return Future(() {
sleep(Duration(seconds: 2));
print('token:$token,存储成功');
return true;
});
}
8. async await 改造
// 用户先登录,登录成功之后拿到token,然后再保存token到本地
import 'dart:io';
void main() {
print('启动');
// login().then((token) {
// setToken(token).then((res) {});
// }).catchError((e) {});
doLogin();
print('结束');
}
doLogin() async {
try {
String token = await login();
bool res = await setToken(token);
if (res) {
print('操作成功');
} else {
print('操作失败');
}
} catch (e) {
print(e);
}
}
// 登录
Future<String> login() {
return Future(() {
sleep(Duration(seconds: 2));
print('登录成功');
// 返回token
return '111111';
});
}
// 存储token
Future<bool> setToken(String token) {
return Future(() {
sleep(Duration(seconds: 2));
print('token:$token,存储成功');
return true;
});
}
9. dynamic 关闭编译器类型检查
/*
dynamic会关闭编译器的类型检查
1. 所以dynamic声明的变量在修改时不会检查类型
2. 代码在编译期不会报错,但是在运行时就会报错
*/
void main() {
List test = ['aaa', 111, true];
List<dynamic> test2 = ['aaa', 'bbb', 22];
List<String> test3 = ['aaa', 'bbb'];
}
10. 泛型
/*
泛型的作用:使用泛型可以减少重复的代码
封装函数:接收字符串就返回字符串,接收数字就返回数字,接收bool就返回bool
*/
void main() {
// 1. 普通封装
// String demoString(String str) {
// return str;
// }
// int demoInt(int a) {
// return a;
// }
// bool demoBool(bool b) {
// return b;
// }
// 2. 基于泛型封装
// T 返回类型 demo<T>:返回类型 T:参数类型
T demo<T>(T parm) {
return parm;
}
// 调用
String ret1 = demo<String>('demo');
print(ret1);
int ret2 = demo<int>(17);
print(ret2);
bool ret3 = demo<bool>(true);
print(ret3);
}