1. extension(扩展)
extension关键字在 Dart 2.7 及其以上才支持- sdk:">=2.7.0<3.0.0"
extension可以扩展对象的内容extension StringExtension on String { // 扩展的内容 }- 扩展不仅可以定义方法,还可以定义
setter、getter、operator
- 使用
- 声明扩展
- 引入扩展
- 使用扩展(
String.扩展内容)
// 扩展内置类
extension StringExtension on String {
// 将字符串形式的数字,转成数字
parseInt() {
return int.parse(this);
}
}
// 扩展自定义类
class Person {
say() {
print('Say something');
}
}
extension StudentPerson on Person {
study() {
print('Study hard');
}
}
void main() {
String number = '20';
print(number.parseInt()); // 20
var p = new Person();
p.say(); // Say something
p.study(); // Study hard
}
2. call
- 在类中可以声明
call方法 (方法名不能变) - 当我们将类的实例,用作函数时,会自动调用
call方法
class IOSPhone {
call(String num) {
print('phone number is $num');
}
}
void main() {
var phone = IOSPhone();
phone('911'); // phone number is 911, 把类的实例,当做函数来使用
IOSPhone()('911'); // 简写方式,(先实例化,再调用)
}
3. noSuchMethod
- 当我们调用了一个类的,未定义的方法时,Dart会自动调用
noSuchMethod - 使用前提
- 类中声明了
noSuchMethod(否则调用默认的noSuchMethod) - 实例化对象必须用
dynamic来修饰dynamic p = Person();
- 调用的是未定义方法(
p.undefinedMethod();)
- 类中声明了
class Person {
say() {
print('say something');
}
@override
noSuchMethod(Invocation invocation) {
print('未定义的方法');
// return super.noSuchMethod(invocation);
}
}
void main() {
dynamic p = new Person();
p.say();
p.study(); // 未定义的方法
}
4. hashCode
hashCode是 Dart 对象的唯一标识hashCode表现为一串数字- Dart 中的每个对象都有
hashCode - 我们可以通过
hashCode来判断两个对象是否相等
class Person {
say() {
print('say something');
}
}
void main() {
var p1 = new Person();
print(p1.hashCode); // 1038920657
var p2 = new Person();
print(p2.hashCode); // 806325257
}
5. typedef
typedef可以用来自定义类型(别名),目的是让程序的可读性更强- 我们可以在声明泛型时,使用自定义的类型
- 语法:
typedef function_name(parameters);typedef variable_name = List<int>;
- 版本声明
- sdk: ">=2.13.0"
- 2.13之前,
typedef仅限于函数类型 - 2.13之后,
typedef可以定义非函数类型
typedef MathOperation(int a, int b);
// 声明加法运算
add(int a, int b) {
print('加法运算:' + (a + b).toString());
return a + b;
}
// 声明减法运算
sub(int a, int b) {
print('减法运算:' + (a - b).toString());
return a - b;
}
// 声明加法运算
add3(int a, int b, int c) {
print('加法运算3:' + (a + b + c).toString());
return a + b + c;
}
// 计算器
calculator(int a, int b, MathOperation op) {
print('计算器:');
op(a, b);
}
void main() {
print(add is MathOperation); // true
print(add is Function); // true
print(sub is MathOperation); // true
print(sub is Function); // true
print(add3 is MathOperation); // false
print(add3 is Function); // true
MathOperation op = add;
op(10, 20); // 加法运算:30
op = sub;
op(20, 10); // 减法运算:10
calculator(8, 5, add);
calculator(8, 5, sub);
}
6. 异步编程
6.1. 单线程(EventLoop)
- Dart 单线程的核心包括:主线程、微任务、宏任务
- 微任务队列
- 微任务队列包含微任务,主要通过
scheduleMicrotask来调度
- 微任务队列包含微任务,主要通过
- 事件队列
- 事件队列包含外部事件,例如:I/O、Timer、绘制事件等
- 微任务队列
- 同步与异步
- 同步(4*100米,接力赛)
- 异步(100米中有8个跑道)
6.2. Isolate 多线程
-
lsolate是 Dart 中的线程- Dart 中的线程是以隔离(
lsolate)的方式存在的 - 每个
lsolate都有自己独立的,私有内存块(多个线程不共享内存) - 没有共享内存,就不需要竞争资源,就不需要锁(不用担心死锁问题)
- Dart 中的线程是以隔离(
-
所有的 Dart 代码,都运行在
lsolate中lsolate提供了 Dart | Flutter 的运行环境- 微任务队列、事件队列、事件轮训(EventLoop)都在
lsolate中进行
-
多线程经常用来解决耗时较长的异步任务
-
lsolate类用来管理线程(创建、暂停、杀死lsolate线程)lsolate.spawn();lsolate.spawnUri();lsolate.pause();lsolate.kill();
6.2.1. 多线程 - 创建
Future<lsolate> lsolate.spawn(entryPoint, message);import 'dart:isolate';entryPoint必须是一个顶层方法或者静态方法message-
- Dart 原始数据类型,如:
null、bool、int、double、String等
- Dart 原始数据类型,如:
-
SendPort实例-ReceivePort().sendPort
- 包含 1 和 2 的
list和map,也可以嵌套
-
compute()import 'package:flutter/foundation.dart';
6.3. Future
6.3.1. 什么是 Future
- 概念
- Future 是 Dart 中的类,我们可以通过 Future 实例,封装一些异步任务
- Future 的含义是未来。未来要执行的一些任务,我们可以放到 Future 中
- Future 有三种状态
- 未完成(Uncompleted)
- 已完成,并返回数据(Completed with data)
- 已完成,但返回报错(Completed with error)
6.3.2. 获取 Future 实例
- 自动返回
final myFuture = http.get('https://my.image.url');final myFuture = SharedPreferences.getInstance;
- 手动创建
final myFuture = Future(() {return 123;});final myFuture = Future.error(Exception());final myFuture = Future.delayed(Duration(seconds: 5), () => 123);
- Future 状态相关的方法
- 创建
- Uncompleted
then()- Completed with data
catchError()- Completed with error
whenComplete()- Completed with data + Completed with error
- 创建
void main() {
// 创建 Future 实例
final f = Future(() {
print('Create the future');
return 123;
});
print(f);
f.then((value) => print(value));
print('Done with main');
}
void main() {
Future.delayed(Duration(seconds: 2), () {
return 123;
// throw Error();
}).then((value) {
print(value);
}).catchError(
(err) {
print(err);
},
test: (error) => error.runtimeType == String,
).whenComplete(() {
print('All Completed');
});
}
6.3.3. Future 执行顺序
- Future 默认是异步任务,会被丢到事件队列(
event queue)中 Future.sync()- 同步任务,同步执行(不会被丢到异步队列中)
Future.microtask()- 微任务,会丢到
microtask queue中,优先级比事件任务高
- 微任务,会丢到
Future.value(val)- val 是常量(等同于
microtask) - val 是异步(按照异步逻辑处理)
- val 是常量(等同于
void main() {
print('start');
Future(() => print('Future() task')); // event queue
Future.sync(() => print('Future.sync() task'));
// 如果 value 后面的值是异步,则按照异步的逻辑进行处理
Future.value(Future(() => print('Future.value future task')));
// 如果 value 后面的值是常量,那么 Future.value 创建的是微任务
Future.value('Future.value() const task').then((value) => print(value));
Future.microtask(() => print('Future.microtask() task')); // microtask queue
print('end');
/*
* start
Future.sync() task
end
Future.value() const task
Future.microtask() task
Future() task
Future.value future task
* */
}
6.3.4. Future 多任务
Future.any(futures);- 返回最先完成的 Future 结果
Future.wait(futures);- 等待所有的 Future 执行完成,并收集所有 Future 的返回结果
Future.doWhile(action);- 按照条件遍历执行多个 Future
Future.forEach(elements, action);- 遍历一个给定的集合,根据集合元素执行多个 Future
void main() {
print('start');
// 返回最先完成的异步任务
Future.any([
Future.delayed(Duration(seconds: 4)).then((value) => 1),
Future.delayed(Duration(seconds: 2)).then((value) => 2),
Future.delayed(Duration(seconds: 3)).then((value) => 3),
]).then((value) => print('多个 Future 的最快的返回结果是:$value'));
// 等待所有异步任务完成,并收集所有异步任务的结果
Future.wait([
Future.delayed(Duration(seconds: 4)).then((value) {
print('Future 1');
return 1;
}),
Future.delayed(Duration(seconds: 2)).then((value) {
print('Future 2');
return 2;
}),
Future.delayed(Duration(seconds: 3)).then((value) {
print('Future 3');
return 3;
}),
]).then((value) => print('所有 Future 的执行结果是:$value'));
var i = 0;
Future.doWhile(() {
i++;
return Future.delayed(Duration(seconds: 2), () {
print(
'Future.doWhile() $i, 当前时间:${DateTime.now().microsecondsSinceEpoch}');
return i < 6;
}).then((value) {
print(value);
return value;
});
}).then((val) {
print('Future.doWhile() then:null');
});
Future.forEach([1, 2, 3], (element) {
return Future.delayed(Duration(seconds: 2), () {
print('当前元素:$element');
return element.toString() + '_AAA';
}).then((value) => print('处理后的结果:$value'));
});
print('end');
}
6.3.5. FutureBuilder
FutureBuilder是 Flutter SDK 中提供的异步组件。FutureBuilder是一个类,接受 Future 数据,并将数据渲染成页面import 'package:flutter/material.dart';
FutureBuilder中有 3 个属性futureinitialDatabuilder(context, snapshot)
6.3.5.1. FutureBuilder - snapshot
snapshot.connectionStateConnectionState.none(未连接异步任务)ConnectionState.waiting(连接异步任务,等待交互)ConnectionState.active(正在交互)ConnectionState.done(异步任务完成)
snapshot.hasData(Completed with data)snapshot.data
snapshot.hasError(Completed with error)
6.4. Stream
6.4.1. 什么是 Stream
-
Stream 是 Dart 中的异步数据流,可以连续不断地返回多个数据
- Future 是异步,但只返回一个值
- Stream 也是异步,可以返回多个值(数据流)
-
Stream 相关的API
- 通过
listen进行数据监听 - 通过
error接收失败状态 - 通过
done来接收结束状态
- 通过
-
Stream 类型
- Single-Subscription(单一订阅)
- 数据流只能被
listen一次(listen 多次会报错) StremaController().streamStream stream = Stream.fromlterable(data)
- 数据流只能被
- Broadcast (广播)
- 数据流可以被
listen多次 StremaController<int>.broadcast();stream.asBroadcastStream();
- 数据流可以被
- Single-Subscription(单一订阅)
import 'dart:async';
void main() {
// 创建单一订阅数据流
final StreamController controller = StreamController();
// 第一次监听
controller.stream.listen((event){
print('Data is $event');
});
// 第二次监听,会报错
// controller.stream.listen((event){
// print('Data is $event');
// });
// 给数据流添加数据
controller.sink.add('abc');
controller.sink.add('123');
}
import 'dart:async';
void main() {
// 创建广播留
StreamController controller = StreamController.broadcast();
// 第一次监听
controller.stream.listen((event){
print('Data1 is $event');
});
controller.sink.add('abc');
// 第二次监听
controller.stream.listen((event){
print('Data2 is $event');
});
// 给数据流添加数据
controller.sink.add('123');
}
6.4.2. 创建 Stream
StreamController类sinkstream
- Stream 类
Stream.fromFuture()Stream.fromFutures()Stream.fromIterable()Stream.periodic()