Dart是单线程的
同步的例子
import 'dart:io';
void main() {
// // 1.验证dart是单线程, 此时必然是getNetwork()这行执行完才会执行之后的打印bbb;如果是多线程语言,不会等到这行代码执行完
print('开始执行主函数--同步');
print(getNetwork());
print('bbb');
}
/**
* 1. 模拟网络请求 (此时是同步的)
*/
String getNetwork() {
sleep(Duration(seconds: 3));
return '获取了网络数据';
}
1. 异步编程
异步编程分为两种:
- 多线程:如C++、Java、鸿蒙,就是用的多线程方式;通过线程间的通信方式 来拿到数据给主线程;
- 单线程:单线程+事件循环;JS、Dart就是的;
(就是一个线程,同步的排到线程上面去(不能是耗时的),耗时的放在“异步”上面,同步的做完了,就执行异步的,不停这样循环)
1.1. Future
1.1.1. 基本使用
import 'dart:io';
void main() {
// 使用Future
print('开始执行主函数--同步');
getNetwork().then((res) {
print(res);
}).catchError((err) {
print(err);
});
print('我是不能被阻塞的同步任务');
}
// 在鸿蒙中针对这些耗时的操作是放在Promiss里面;而Dart也有类似的东西,叫:Future
// 以下就是Future的写法 (这里是模拟把异步的内容写在Future中,这个Futurn是什么呢?就是能自动将本来不异步的变为异步)
Future<String> getNetwork() {
return Future(() {
sleep(Duration(seconds: 3));
return '成功获取了网络数据';
});
}
1.1.2. Future链式调用 (.then().catchError()这种写法就是链式调用)
链式调用:就是写.then().catchError()这种写法就是链式调用;
重点:在实际使用中,这个Future不一定是自己写出来创建的,也可能是调用内部API或第三方那个API获取到一个Future;
鸿蒙中的Promise有三种状态:当初始态 进入 成功态或失败态时 都是不能回退的;
- 初始态(pending):表示异步操作尚未完成,既没有被兑现,也没有被拒绝;
- 成功态(fulfilled):当Promise实例中异步任务成功完成并返回结果时,状态从初始态 进入 成功态;
- 失败态(rejected):当Promise实例中异步任务执行失败时;状态从初始态 进入 失败态;
但Dart中的Future只有两种状态:
- 未完成状态(uncompleted):执行Future的异步操作时,当运行后还在 等待时还没返回结果时(例如案例中模拟的延时) 此时就是未完成状态;
- 完成状态(completed):当Future的异步操作执行完成 并返回结果 或 抛出一个异常,这都是完成状态(不像Promise);
import 'dart:io';
void main() {
// // 1.验证dart是单线程, 此时必然是getNetwork()这行执行完才会执行之后的打印bbb;如果是多线程语言,不会等到这行代码执行完
// print('开始执行主函数--同步');
// print(getNetwork());
// print('bbb');
// 2.使用Future
print('开始执行主函数--同步');
getNetwork().then((res) {
print(res);
}).catchError((err) {
print(err);
});
print('我是不能被阻塞的同步任务');
}
// 在鸿蒙中针对这些耗时的操作是放在Promiss里面;而Dart也有类似的东西,叫:Future
/**
* 1. 模拟网络请求 (此时是同步的)
*/
// String getNetwork() {
// sleep(Duration(seconds: 3));
// return '获取了网络数据';
// }
// 2. 以下就是Future的写法 (这里是模拟把异步的内容写在Future中,这个Futurn是什么呢?就是能自动将本来不异步的变为异步)
Future<String> getNetwork() {
return Future(() {
sleep(Duration(seconds: 3));
// return '成功获取了网络数据';
throw '网络请求出现了异常'; //这就是抛出一个异常,类比是网络请求出现错误时,在上面写的catchError就能捕获到(只会打印出这里自己设定的文字,而不会报错);
});
}
1.1.3. Future链式调用小练习
// 用户先登录,登录成功之后拿到token,然后再保存token到本地
import 'dart:io';
void main() {
print('同步任务---a');
//异步任务
login().then((tok) {
// 拿到token并保存到本地
saveToken(tok).then((res) {
print('成功...$res');
});
}).catchError((err) {
print('出现了错误:$err');
});
print('同步任务---b');
}
/**
* 登录
*/
Future<String> login() {
return Future(() {
sleep(Duration(seconds: 3));
print('登录完成');
return '012qweqweqweqweqweqw';
});
}
/**
* 保存token
*/
Future<bool> saveToken(String token) {
return Future(() {
sleep(Duration(seconds: 2));
print('token已保存,token是$token');
return true;
});
}
1.2. async和await
// 用户先登录,登录成功之后拿到token,然后再保存token到本地
import 'dart:io';
void main() {
print('同步任务---a');
//异步任务
logSa();
print('同步任务---b');
}
logSa() async {
try {
String token = await login();
bool saveSta = await saveToken(token);
if (saveSta) {
print('整个操作结果成功');
} else {
print('整个操作结果失败');
}
} catch (e) {
print(e);
}
}
/**
* 登录
*/
Future<String> login() {
return Future(() {
sleep(Duration(seconds: 3));
print('登录完成');
return '012qweqweqweqweqweqw';
});
}
/**
* 保存token
*/
Future<bool> saveToken(String token) {
return Future(() {
sleep(Duration(seconds: 2));
print('已获取到token,token是$token');
// return true;//模拟操作成功
throw Exception('出现了异常'); //模拟操作失败
});
}
1.3. 泛型
1.3.1. dynamic类型 及 泛型的用法-List/Map定义中
/**
* dynamic 会关闭编译器的类型检查
* 1. 所以dynamic声明的变量在修改时不会检查类型
* 2. 代码在编译器不会报错,但是在运行时就会报错
*/
void main() {
// 1. List/Map不用泛型的写法, 此时里面可以写任何类型
// List arr = [11, 'asd', false];
// Map m = {123: 'qq', '阿斯达': 123, false: true};
// 2. 使用泛型的写法, 此时可以限制里面只能写什么类型
List<num> arr = [11, 22, 15]; //这样就只能写num数字类型了
Map<String, dynamic> m = {
'123': 'qq',
'阿斯达': 123,
'false': true
}; //此时<String, dynamic>中的dynamic是任意类型, <String, dynamic>说明里面的键值对格式必须按照这个格式来:{键必须是String : 值可以是任意类型, 键必须是String : 值可以是任意类型...}
}
1.3.2. 泛型-函数
/**
* 泛型的使用: 使用泛型可以减少重复的代码
* 封装函数: 接收字符串就返回字符串,接收数字就返回数字,接收bool就返回bool
*/
void main() {
// // 1.普通封装
// getValue(5);
// getValue('aaa'); //此时入参不是数字就会报错,不灵活
// getValue(true); //此时入参不是数字就会报错,不灵活
// 2.基于泛型封装
getValue<num>(12);
getValue<String>('aaa');
getValue<bool>(true);
}
// // 1.普通封装
// num getValue(num number) {
// return number;
// }
// 2.基于泛型封装 在方法后面加一个<T>,也相当于一个入参,只不过这个入参是 类型(在调用的时候也需要加<>尖括号,然后尖括号里要写上具体的 "类型入参");
// 方法中写了<T>后, 它在方法体中需要用到类型的地方都可以使用
T getValue<T>(T numbera) {
return numbera;
}
1.4. 异常处理
- try...catch...finally
- if...else: 处理返回的是true或false的 ,或者说返回的是正常或不正常的,如果不正常,就手动抛出异常;
void main() {
// 1. 捕获异常:try catch
// try {
// dynamic name = 'itheima';
// name.haha();
// } catch (e) {
// print(e);
// } finally {
// // 无论是否有异常都会执行这个代码块
// print('finally');
// }
// 2. 手动抛出异常:判断字符串是否相等,如果不相等手动抛出异常
try {
String str = 'itcast';
if (str == 'yjh') {
print('ok');
} else {
// 手动抛出异常
throw Exception('字符串不相等');
}
} catch (e) {
print(e);
}
}
```**Dart是单线程的**
## 同步的例子
import 'dart:io';
void main() { // // 1.验证dart是单线程, 此时必然是getNetwork()这行执行完才会执行之后的打印bbb;如果是多线程语言,不会等到这行代码执行完 print('开始执行主函数--同步'); print(getNetwork()); print('bbb'); }
/**
-
- 模拟网络请求 (此时是同步的) */ String getNetwork() { sleep(Duration(seconds: 3)); return '获取了网络数据'; }
# 1. 异步编程
异步编程分为两种:
1. **多线程**:如C++、Java、鸿蒙,就是用的多线程方式;通过**线程间的通信方式** 来**拿到数据**给**主线程**;
1. **单线程**:单线程+事件循环;JS、Dart就是的;
(就是一个线程,同步的排到线程上面去(不能是耗时的),耗时的放在“异步”上面,同步的做完了,就执行异步的,不停这样循环)
## 1.1. Future
### 1.1.1. 基本使用
import 'dart:io';
void main() { // 使用Future print('开始执行主函数--同步'); getNetwork().then((res) { print(res); }).catchError((err) { print(err); }); print('我是不能被阻塞的同步任务'); }
// 在鸿蒙中针对这些耗时的操作是放在Promiss里面;而Dart也有类似的东西,叫:Future
// 以下就是Future的写法 (这里是模拟把异步的内容写在Future中,这个Futurn是什么呢?就是能自动将本来不异步的变为异步) Future getNetwork() { return Future(() { sleep(Duration(seconds: 3)); return '成功获取了网络数据'; }); }
### 1.1.2. **Future**链式调用 (.then().catchError()这种写法就是链式调用)
**链式调用**:就是写.then().catchError()这种写法就是链式调用;
**重点**:在实际使用中,这个Future不一定是自己写出来创建的,也可能是调用内部API或第三方那个API获取到一个Future;
**鸿蒙中的Promise有三种状态**:当初始态 进入 成功态或失败态时 都是不能回退的;
1. 初始态(pending):表示异步操作尚未完成,既没有被兑现,也没有被拒绝;
1. 成功态(fulfilled):当Promise实例中异步任务成功完成并返回结果时,状态从初始态 进入 **成功态**;
1. 失败态(rejected):当Promise实例中异步任务执行失败时;状态从初始态 进入 **失败态**;
**但Dart中的Future只有两种状态**:
1. 未完成状态(uncompleted):执行Future的异步操作时,当运行后还在 **等待时还没返回结果时**(例如案例中模拟的延时) 此时就是未完成状态;
1. 完成状态(completed):当Future的异步**操作执行完成 并返回结果** 或 **抛出一个异常**,这都是完成状态(不像Promise);
import 'dart:io';
void main() { // // 1.验证dart是单线程, 此时必然是getNetwork()这行执行完才会执行之后的打印bbb;如果是多线程语言,不会等到这行代码执行完 // print('开始执行主函数--同步'); // print(getNetwork()); // print('bbb');
// 2.使用Future print('开始执行主函数--同步'); getNetwork().then((res) { print(res); }).catchError((err) { print(err); }); print('我是不能被阻塞的同步任务'); }
// 在鸿蒙中针对这些耗时的操作是放在Promiss里面;而Dart也有类似的东西,叫:Future /**
-
- 模拟网络请求 (此时是同步的) */ // String getNetwork() { // sleep(Duration(seconds: 3)); // return '获取了网络数据'; // }
// 2. 以下就是Future的写法 (这里是模拟把异步的内容写在Future中,这个Futurn是什么呢?就是能自动将本来不异步的变为异步) Future getNetwork() { return Future(() { sleep(Duration(seconds: 3)); // return '成功获取了网络数据'; throw '网络请求出现了异常'; //这就是抛出一个异常,类比是网络请求出现错误时,在上面写的catchError就能捕获到(只会打印出这里自己设定的文字,而不会报错); }); }
### 1.1.3. **Future**链式调用小练习
// 用户先登录,登录成功之后拿到token,然后再保存token到本地
import 'dart:io';
void main() { print('同步任务---a'); //异步任务 login().then((tok) { // 拿到token并保存到本地 saveToken(tok).then((res) { print('成功...res'); }); }).catchError((err) { print('出现了错误:err'); });
print('同步任务---b'); }
/**
- 登录 */ Future login() { return Future(() { sleep(Duration(seconds: 3)); print('登录完成'); return '012qweqweqweqweqweqw'; }); }
/**
- 保存token */ Future saveToken(String token) { return Future(() { sleep(Duration(seconds: 2)); print('token已保存,token是$token'); return true; }); }
## 1.2. async和await
// 用户先登录,登录成功之后拿到token,然后再保存token到本地
import 'dart:io';
void main() { print('同步任务---a'); //异步任务 logSa();
print('同步任务---b'); }
logSa() async { try { String token = await login(); bool saveSta = await saveToken(token); if (saveSta) { print('整个操作结果成功'); } else { print('整个操作结果失败'); } } catch (e) { print(e); } }
/**
- 登录 */ Future login() { return Future(() { sleep(Duration(seconds: 3)); print('登录完成'); return '012qweqweqweqweqweqw'; }); }
/**
- 保存token */ Future saveToken(String token) { return Future(() { sleep(Duration(seconds: 2)); print('已获取到token,token是$token'); // return true;//模拟操作成功 throw Exception('出现了异常'); //模拟操作失败 }); }
## 1.3. 泛型
### 1.3.1. dynamic类型 及 泛型的用法-List/Map定义中
/**
- dynamic 会关闭编译器的类型检查
-
- 所以dynamic声明的变量在修改时不会检查类型
-
- 代码在编译器不会报错,但是在运行时就会报错 */ void main() { // 1. List/Map不用泛型的写法, 此时里面可以写任何类型 // List arr = [11, 'asd', false]; // Map m = {123: 'qq', '阿斯达': 123, false: true};
// 2. 使用泛型的写法, 此时可以限制里面只能写什么类型 List arr = [11, 22, 15]; //这样就只能写num数字类型了 Map<String, dynamic> m = { '123': 'qq', '阿斯达': 123, 'false': true }; //此时<String, dynamic>中的dynamic是任意类型, <String, dynamic>说明里面的键值对格式必须按照这个格式来:{键必须是String : 值可以是任意类型, 键必须是String : 值可以是任意类型...} }
### 1.3.2. 泛型-函数
/**
- 泛型的使用: 使用泛型可以减少重复的代码
- 封装函数: 接收字符串就返回字符串,接收数字就返回数字,接收bool就返回bool */
void main() { // // 1.普通封装 // getValue(5); // getValue('aaa'); //此时入参不是数字就会报错,不灵活 // getValue(true); //此时入参不是数字就会报错,不灵活
// 2.基于泛型封装 getValue(12); getValue('aaa'); getValue(true); }
// // 1.普通封装 // num getValue(num number) { // return number; // }
// 2.基于泛型封装 在方法后面加一个,也相当于一个入参,只不过这个入参是 类型(在调用的时候也需要加<>尖括号,然后尖括号里要写上具体的 "类型入参"); // 方法中写了后, 它在方法体中需要用到类型的地方都可以使用 T getValue(T numbera) { return numbera; }
## 1.4. 异常处理
- try...catch...finally
- if...else: 处理返回的是true或false的 ,或者说返回的是正常或不正常的,如果不正常,就手动抛出异常;
void main() { // 1. 捕获异常:try catch // try { // dynamic name = 'itheima'; // name.haha(); // } catch (e) { // print(e); // } finally { // // 无论是否有异常都会执行这个代码块 // print('finally'); // }
// 2. 手动抛出异常:判断字符串是否相等,如果不相等手动抛出异常 try { String str = 'itcast'; if (str == 'yjh') { print('ok'); } else { // 手动抛出异常 throw Exception('字符串不相等'); } } catch (e) { print(e); } }