dart 语法进阶
1. 接口 abstract
implements
java 中是interface
abstract class Processor {
late String cores;
arch(String name) {}
}
abstract class Camera {
late String resolution;
brand(String name);
}
class Phone implements Processor, Camera {
@override
arch(String name) {
print(name);
}
@override
brand(String name) {
print(name);
}
@override
String cores;
@override
String resolution;
Phone()
: cores = '3',
resolution = 'name';
}
void main() {
print("hello world");
var phone = Phone();
}
2. mixin 提高代码的复用度
- class mixin 关键字都可已推荐 mixin
- with 可以是多个 ”,“ 分割,后面的属性和方法重名会覆盖前面的
- 用作混入的类不能有构造函数
- mixin 类只能继承 Object
// class mixin
class MixinA {
String name = 'MixinA';
void showInfo() {
print(name);
}
}
mixin MixinB {
// MixinB(); 用作混入的类不能有构造函数
String name = 'MixinB';
void showInfo() {
print(name);
}
}
class MixinTest with MixinA, MixinB {}
void main() {
print("hello world");
var mixinTest = MixinTest();
print(mixinTest.name);
}
3. extension 扩展
//扩展内置类
extension StringExt on String {
int parseInt() {
return int.parse(this);
}
}
//扩展自定义类
class Person {
final String name;
Person(this.name);
}
extension PersonExt on Person {
info() {
print(this.name);
}
}
4. call
-
在类中可以声明call 方法
-
类的实例当做行数使用
void main(List<String> args) { var phone = Phone();//将类的实例当做函数使用 phone('18614060661'); } class Phone { call(String num) { print('phone number is $num'); } }
5. noSuchMethod
class Person {
final String name;
Person(this.name);
@override
noSuchMethod(Invocation invocation) {
return super.noSuchMethod(invocation);
}
}
void main(List<String> args) {
//dynamic 修饰
dynamic p = Person('zhu');
p.say();
}
6. hashCode
- dart 对象的唯一标识
- 表现为一串数字 // eg: obj.hashCode; 608635269
- 可以判断两个对象是否是同一个内存地址
7. typedef
- 自定义别名
- 语法
- typedef function_name (parmas)
- typedef variable_name=List<int> (dart:2.13之后)
typedef MathOperation = Function(int a, int b);
fn1(int a, b) {
return a + b;
}
void main(List<String> args) {
if (fn1 is MathOperation) {
print('true');
} else {
print('false');
}
}
8.eventLoop 事件轮询机制
image.png image.png9 isolate
- isolate 是dart 中的线程
- 每个isolate都有自己的独立的私有内存(多个isolate不共享内存)
- dart中的线程是以 隔离(isolate)的方式存在
- 没有共享没存,不存在资源竞争(不需要锁,也就没有死锁)
- 所有dart 都运行在isolate中
- isolate 提供了dart | flutter 的运行环境
- 微任务队列、事件队列、事件轮询 都在isolate 中进行
- 多线程长用来解决耗时较长的异步任务
- isolate的位置
9.1 isolate 多线程-创建
-
Isolate 类 用来管理线程(创建、暂停、杀死 Isolate线程)
Isolate.spawn();//创建线程 Isolate.spawnUri();//跨文件 函数创建线程 Isolate.pause();//暂停 Isolate.kill();//杀死
import 'dart:isolate';
/*
entryPoint : 必须是一个顶层方法或静态方法
message:
1. dart 原始类型 eg:null,int,String ...
2. SendPort 实例 ReceivePort().sendPort
3. 包含 1 和 2 的list、 map 可以嵌套
*/
static Future<Isolate> spawn<T>(void entryPoint(T message), T message);
import 'package:flutter/foundation.dart'
compute();
-
使用实例1:创建一个线程
import 'dart:isolate'; void main() { test(); } void test() async { print('---start---'); print('thead: ${Isolate.current.debugName}'); Isolate.spawn(newThread1, 'zhu'); //一般 异步执行 print('---end---'); /* end 和 子线程打印顺序不固定 ---start--- thead: main ---end--- thead: newThread1 message:zhu ---start--- thead: main thead: newThread1 message:zhu ---end--- */ } void newThread1(dynamic message) { print('thead: ${Isolate.current.debugName} message:$message'); }
-
实例2 创建多个线程
import 'dart:isolate'; void main(List<String> args) { test(); } void test() async { print('---start---'); print('thead: ${Isolate.current.debugName}'); Isolate.spawn(newThread1, 'zhu'); Isolate.spawn(newThread2, true); Isolate.spawn(newThread3, 1000); print('---end---'); } void newThread1(dynamic message) { print('thead: ${Isolate.current.debugName} message:$message'); } void newThread2(dynamic message) { print('thead: ${Isolate.current.debugName} message:$message'); } void newThread3(dynamic message) { print('thead: ${Isolate.current.debugName} message:$message'); }
9.2 多线程通信机制-Port
-
isolate 多线程之间通信的唯一方式是 Port
-
ReceivePort 类,初始化接受端口,创建发送端口,接受消息、监听消息、关闭端口
-
SendPort 类 将消息发送给ReceivePort
-
通信方式
- 单项通信:A -> B
- 双向通信:A <-> B
- image.png
import 'dart:isolate';
void main(List<String> args) {
test();
}
test() {
print('---start---');
print(Isolate.current.debugName);
//创建接收端口
ReceivePort receivePort = ReceivePort();
//建立监听
receivePort.listen((message) {
print('listen: $message');
//关闭监听
receivePort.close();
});
//获取发送端口
SendPort sendPort = receivePort.sendPort;
Isolate.spawn(mutilThead, sendPort);
print('---end---');
}
void mutilThead(message) {
print(Isolate.current.debugName);
print(message);
SendPort sendPort = message as SendPort;
sendPort.send('mutilThead 发来的消息');
}
image.png
import 'dart:isolate';
void main(List<String> args) async {
print('---start---');
print(Isolate.current.debugName);
//创建接收端口
ReceivePort r1 = ReceivePort();
//建立监听
//获取发送端口
SendPort p1 = r1.sendPort;
Isolate.spawn(newThead, p1);
SendPort p2 = await r1.first;
var msg = await sendToReceive(p2, 'hello');
print('主线程接收到:$msg');
print('---end---');
}
Future sendToReceive(SendPort sendPort, dynamic msg) async {
print('${Isolate.current.debugName} 发送消息: $msg');
ReceivePort receivePort = ReceivePort();
sendPort.send([receivePort.sendPort, msg]);
return receivePort.first;
}
void newThead(SendPort p1) async {
var r2 = ReceivePort();
p1.send(r2.sendPort);
await for (var msg in r2) {
var data = msg[1];
print('新线程收到了主线程的消息:$data');
SendPort replyPort = msg[0];
//回复消息
replyPort.send('子线程答复->$data');
}
}
/*
---start---
main
main 发送消息: hello
新线程收到了主线程的消息:hello
主线程接收到:子线程答复->hello
---end---
*/
-
Isolate.spawnUri
import 'dart:isolate'; void main(List<String> args) { print('start'); newIsolate(); print('end'); } void newIsolate() async { ReceivePort r1 = ReceivePort(); SendPort p1 = r1.sendPort; var childThead = await Isolate.spawnUri( Uri(path: 'child_isolate.dart'), ['data1', 'data2', 'data3'], p1); r1.listen((message) { print('主线程收到消息:$message'); if (message[0] == 0) { print('加载中'); } else if (message[0] == 1) { print('处理中'); } else if (message[0] == 2) { print('初始完成'); r1.close(); childThead.kill(); } }); }
//child_isolate.dart import 'dart:io'; import 'dart:isolate'; void main(List<String> args, SendPort p1) { print('${Isolate.current.debugName} 收到:$args'); p1.send([0, '加载中']); sleep(Duration(seconds: 1)); p1.send([1, '处理中']); sleep(Duration(seconds: 1)); p1.send([2, '处理完成']); }
10.Future (类似js 中的Promise)
10.1初始
-
概念
-
Future 是dart 中的类,我们可以通过Future 实例封装一些异步任务
-
Future 含义是未来。未来要执行的任务可以放到Future中
-
-
Future 的三种状态
- 未完成 (Uncompleted)
- 已完成,并返回数据(Complete with data)
- 已完成,但返回错误(Complete with error)
-
获取实例
-
自动返回
- final myFuture = http.get('http://xxxx')
- final myFuture = SharePreferences.getInstace;
-
手动创建
- final myFuture = Future((){return 123;});
- final myFuture = Future.error(Exception());
- Final myFuture = Future.delayed(Duration(seconds:3),(){return 123;});
-
-
状态相关方法
- 创建
- Uncomplete
- then()
- Complate with data
- catchError()
- Complate with error
- whenComplate()
- Complate with data + Complate with error
- 创建
void main(List<String> args) {
test();
}
void test() {
print('start');
var myFuture = Future.delayed(Duration(seconds: 3), () {
throw '异常数据';
});
myFuture.then((value) => print(value)).catchError((error) {
print('error : ' + error);
}, test: (error) => error.runtimeType == String).whenComplete(
() => print('complate'));
print('end');
}
/*
start
end
error : 异常数据
complate
*/
10.2 Future执行顺序
-
Future 默认是异步任务,会被丢到事件队列(event queue)中
-
Future.sync()
- 同步任务,同步执行(不会丢到异步队列)
-
Future.microtast()
- 微任务丢到microtask queue 中优先级比event queue 高
-
Future.value(val)
-
val 是常量 (等同microtask)
-
val 是异步(按照异步任务处理)
-
10.3 多任务
-
Future.any(Futures) 返回最先完成的Future结果
-
Future.wait(Futures) 等待所有的Future完成,并返回所有Future的结果
-
Future.doWhile(action) 按照条件遍历执行多个Future
-
Future.forEach(elements,action) 遍历一个给定的集合,根据集合元素执行多个Future
10.4. FutureBuilder - snapshot
- snapshot.connectionState
- ConnectionState.none (未连接异步任务)
- ConnectionState.waiting (连接异步任务,等待交互)
- ConnectionState.active (连接异步任务,正在交互)
- ConnectionState.done (异步任务完成)
-
snapshot.hasData
-
snapshot.hasError
11.Stream
11.1 Stream 概念
Stream 是Dart 中异步数据流,可以连续不断地返回多个数据。
- Future是异步 ,单只返回一个值
- Stream也是异步,可以返回多个值(数据流)
Stream 相关的API
- 通过listen进行数据监听
- 通过error 接受失败状态
- done来接收结束状态
11.2 Stream 类型
Single-Subscription (单一订阅)
- 数据流只能listen 一次(listen 多次会报错)
- StreamController().stream
- Stream stream = Stream.fromIterable(data)
import 'dart:async';
void main(List<String> args) {
//创建一次订阅数据流控制器
StreamController streamController = StreamController();
//一次监听 只能监听一次
streamController.stream.listen((event) {
print('接收到数据:$event');
});
//sink数据槽 添加数据
streamController.sink.add('123');
streamController.sink.add('abc');
/*
接收到数据:123
接收到数据:abc
*/
}
Broadcase (广播)
- 数据流可以被 listen 多次
- StreamController<int>.broadcast();
- stream.asBroadcastStream()
import 'dart:async';
void main(List<String> args) {
//创建多次订阅数据流控制器
StreamController streamController = StreamController.broadcast();
streamController.stream.listen((event) {
print('第一次监听接收到数据:$event');
});
//sink数据槽 添加数据
streamController.sink.add('123');
streamController.stream.listen((event) {
print('第二次监听接收到数据:$event');
});
streamController.sink.add('abc');
/*
第一次监听接收到数据:123
第二次监听接收到数据:abc
第一次监听接收到数据:abc
*/
}
11.3 创建 Stream 实例
StreamController 类
- sink
- stream
Stream 类
- Stream.fromFuture();
- Stream.fromFutures();
- Stream.fromIterable();
- Stream.periodic();
Future<String> getFuture() async {
await Future.delayed(Duration(seconds: 2), () {});
return DateTime.now().toString();
}
void main(List<String> args) async {
Stream.fromFuture(getFuture()).listen((event) {
print('fromFuture 接收到数据 : $event');
}, onDone: () {
print('fromFuture onDone');
});
Stream.fromFutures([getFuture(), getFuture(), getFuture()]).listen((event) {
print('fromFutures 接收到数据 : $event');
});
Stream.fromIterable([123, 'acb', null]).listen((event) {
print('fromIterable 接收到数据 : $event');
});
}
/*
fromIterable 接收到数据 : 123
fromIterable 接收到数据 : acb
fromIterable 接收到数据 : null
fromFuture 接收到数据 : 2022-09-21 23:01:08.346103
fromFuture onDone
fromFutures 接收到数据 : 2022-09-21 23:01:08.355317
fromFutures 接收到数据 : 2022-09-21 23:01:08.355797
fromFutures 接收到数据 : 2022-09-21 23:01:08.355834
*/
Stream.periodic();
void main(List<String> args) {
// Stream.periodic(Duration(seconds: 1), (int data) => data).listen((event) {
// print('收到数据:$event'); //收到数据:null
// });
Stream.periodic(Duration(seconds: 1), (int data) => data).take(5) //接收5次数据
.listen((event) {
print('收到数据:$event');
}, onDone: () => print('periodic done'));
/*
收到数据:0
收到数据:1
收到数据:2
收到数据:3
收到数据:4
periodic done
*/
}
11.4 Stream 操作
-
take(int count) | takeWhile() 取count次
-
where()
-
distinct() //去重 去掉和前一个数据相同的数据(连续重复值)
-
skip(int count) | skipWhile() 跳过count个
-
map()
-
toSet() | toList() | toString()
-
length | first | last
-
.... 等等
12.Generator(生成器)
概念:生成器是有一种特殊的函数,返回值通过yield 关键词来指定
分类
-
同步生成器(sync + yield),yield==return + continue
- 使用 sync* ,返回是Iterable 对象
- yeild 会返回moveNext为true,并等待moveNext指令
-
异步生成器(async + yield)
- 使用 async* ,返回是Stream 对象
- yeild不用暂停,数据以流的方式一次性推送
-
递归生成器 (yeild*)
- yeild* 是指针,指向递归函数
同步生成器(sync + yield)
void main(List<String> args) {
var nums = getNumber(5).iterator;
while (nums.moveNext()) {
print(nums.current);
}
}
Iterable<int> getNumber(int n) sync* {
print('start');
var i = 0;
while (i < n) {
yield i++;
}
print('end');
/*
start
0
1
2
3
4
end
*/
}
异步生成器(async + yield)
void main(List<String> args) {
print('start');
var stream = getNumbers(5);
stream.listen((event) {
print('接收到数据:$event');
}, onDone: () {
print('done');
});
print('end');
/*
start
end
接收到数据:0
接收到数据:1
接收到数据:2
接收到数据:3
接收到数据:4
done
*/
}
Stream<int> getNumbers(int n) async* {
var i = 0;
while (i < 5) {
yield i++;
}
}
递归生成器 (yeild*)
void main(List<String> args) {
print('start');
var res = getRange(1, 5);
res.forEach((element) {
print(element);
});
print('end');
}
Iterable<int> getRange(int start, int end) sync* {
if (start <= end) {
yield start;
// for (var j in getRange(start + 1, end)) {
// yield j;
// } //等价写法
yield* getRange(start + 1, end);
}
/*
start
1
2
3
4
5
end
*/
}