高级
extension(扩展)
- extension 关键字在 Dart2.7 及其以上才支持
- sdk ">=2.7.0<3.0.0"
- extension 可以扩展对象的内容
- extension StringExtension on String{// 扩展的内容}
- 扩展不仅可以定义方法,还可以定义 setter,getter,operatior
- 使用
- 声明扩展
- 引入扩展
- 使用扩展(String.扩展内容)
//扩展内部类
extension StringExtension on String{
//将字符串形式的数字,转成数字
parseInt(){
return int.parse(this);
}
}
//扩展自定义类
class Person{
say(){
print('Say something');
}
}
extension StudentPerson on Person{
study(){
print('student2')
}
}
main(){
String number = "20";
print(number.parseInt(number));
var p = Person();
print(p.say());
print(p.study);
}
call
- 在类中可以声明 call 方法(方法名不能变)
- 当我们将类的实例,用作函数时候,会自动调用 call 方法

main(){
var phone = IOSPhone();
phone('911');//将类对象用作函数名 调用call方法
}
class IOSPhone{
call(String num){
print('phone number is $num');
}
}
noSuchMethod
- 当我们调用了一个类的,未定义的方法时,Dart 会自动调用 noSuchMethod
- 使用前提
- 类中声明了 noSuchMethod(否则调默认的 noSuchMethod)
- 实例化对象必须用 dynamic 来修饰
- dynamic p = Person();
- 调用的是未定义方法(p.undefinedMethod())
class Person{
say(){
print('say something');
}
noSuchMethod(Invocatio invocation){
print('未定义的方法');
return super.noSuchMethod(invocation);
}
}
main(){
var p = Person();// dynamic p = Person();
print(p.say());
print(p.study());//这里会报错 为了避免报错Person中增加 noSuchMethod var改成 dynamic
}
hashCode
- hashCode 是 Dart 对象的唯一标识
- hashCode 表示未一串数字
- Dart 中的每个对象都有 hashCode
- 我们可以通过 hashCode 来判断两个对象是否相等
class Person{
say(){
print('Say something');
}
}
main(){
var p1 = Person();
print(p1.hashCode);
//单例
var ps1 = PersonSingleton();
print(ps1.hashCode);
var ps2 = PersonSingleton();
print(ps2.hashCode);
print(ps1==ps2);// true
}
//单例
class PersonSingleton{
static PersonSingleton instance;
PersonSingleton._internal();
static getInstance(){
if(instance ==null){
instance = PersonSingleton._internal();
}
}
factory PersonSingleton()=>getInstance();<int>
}
typedef (type define 或 type defination 缩写)
- typedef 可以用来自定义类型(别名)
- 语法
- typedef function_name(parameters);
- typedef variable_name = List<int>; //2.13 之后
- 版本声明
- sdk:">=2.13.0<3.0.0"
- 2.13 之前,typedef 仅限于函数类型
- 2.13 之后,typedef 可以定义非函数类型
typedef MathOperation(int a,int b);
add(int a,int b){
print('加法运算');
return a+b;
}
add3(int a,int b,c int){
print('加法运算');
return a+b;
}
main(){
print(add is MathOperation);//true
print(add3 is MathOperation);//false
print(add is Function);//true
print(add3 is Function);//true
}
异步编程
- 单线程(EventLoop)
- Isolate 多线程
- Future
- Stream
- Async/Await
- Generator
单线程 EventLoop
- Dart 单线程的核心包括:单线程,微任务和宏任务
- 微任务队列
- 微任务队列包含微任务,主要通过 scheduleMicrotask 来调度。
- 事件队列
- 事件队列包含外部时间,例如 I/O Timer 绘制事件等
- 微任务队列
- 同步和异步
- 同步(4*100 米)
- 异步(100 米中有 8 个跑道)

跟浏览器的差不多

Isolate 多线程
- Isolate 是 Dart 中的线程
- Dart 中的线程是以隔离(Isolate)的方式存在的
- 每个 Isolate 都有自己独立的,私有的内存块( 多个线程不共享内存)
- 没有共享内存,就不需要竞争资源,就不需要锁(不用担心死锁问题)
- 所有的 Dart 代码,都运行在 Isolate 中
- Isolate 提供了 Dart|Fluter 的运行环境
- 微任务队列,事件队列,事件轮询(EventLoop)都在 Isolate 中运行
- 多线程经常用来解决耗时较长的异步任务

Isolate 多线程-创建
Isolate 类来管理线程(创建,暂停 杀死 Isolate 线程)
- Isolate.spawn() 创建线程 直接调用当前文件中的函数
- Isolate.spawnUri() 创建线程调用另外文件中的函数
- Isolate.pause() 暂停进程
- Isolate.kill()
涉及函数:
- Future<Isolate>Isolate.spawn(entryPoint,message)
- import 'dart:isolate';
- entryPoint (必须是一个顶层方法或静态方法)
- message
- 1.Dart 原始数据类型 如 null bool int double String 等
- 2.SendPort 实例-ReceivePort().sendPort
- 包含 1 和 2 的 list 和 map,也可以嵌套
- compute()
- import 'package:flutter/foundation.dart';
import 'dart:isolate';
main(){
multiThread();
}
void multiThread(){
print('multiThread start');
print('当前线程:'+ Isolate.current.debugName);//main
Isolate.spawn(newThread,'hello');
Isolate.spawn(newThread,'hello2');//同一个线程,要使用不同的函数创建不同线程
print('multiThread end');
}
void newThread(String message){
print('当前线程:'+ Isolate.current.debugName);//newThread
print(message);//hello
}
Isolate 多线程通信机制
- Isolate 多线程之间,通信的唯一方式是 Port
- ReceivePort 类
- 初始化接受端口,创建发送端口,接受消息,监听消息,关闭端口
- SendPort 类
- 将消息发送给 ReceivePort
- 通信方式
- 单向通信(a->b)
- 双向通信(a<->b)


单向通信
import 'dart:isolate';
main(){
multiThread();
}
void multiThread(){
print('multThread start');
print('当前线程:'+ Isolate.current.debugName);
ReceivePort r1 = ReceivePort();
SendPort p1 = r1.sendPort;
Isolate.spawn(newThread,p1);
//接收新线程发送过来的消息
//var msg = r1.first;
//print('来自新线程的消息'+ msg.toString());
//接受新线程消息2
r1.listen((msg){
print('来自新线程的消息'+ msg.toString());
r1.close();//关闭端口 不然会处于阻塞状态
})
print('multiThread end');
}
void newThead(SendPort p1){
print('当前线程:'+ Isolate.current.debugName);
//发送消息给main线程
p1.send('abc');
}
双向通信
import 'dart:isolate';
main(){
multiThread();
}
void multiThread()async{
print('multThread start');
print('当前线程:'+ Isolate.current.debugName);
ReceivePort r1 = ReceivePort();
SendPort p1 = r1.sendPort;
Isolate.spawn(newThread,p1);
//接收新线程发送过来的消息
//var msg = r1.first;
//print('来自新线程的消息'+ msg.toString());
//接受新线程消息2
//r1.listen((msg){
// print('来自新线程的消息'+ msg.toString());
// r1.close();//关闭端口 不然会处于阻塞状态
//})
SendPort p2 = await r1.fist;
//p2.send('来自主线程的消息');
var msg = await sendToReceive(p2,'hello');
print('主线程接收到:$msg');
print('multiThread end');
}
void newThead(SendPort p1)async{
print('当前线程:'+ Isolate.current.debugName);
ReceivePort r2 = ReceivePort();
Sendport p2 = r2.sendPort;
p1.send(p2);
//r2.listen(message){
// print(message);//来自主线程消息
// }
await for (var msg in r2){
var data = msg[0];
print('新线程收到了来之主线程的消息:$data');
SendPort replayPort = msg[1];
replayPort.send(data);
}
}
Future sendToReceive(SendPort port,msg){
print('发送消息给新线程'+msg.toString());
ReceivePort response = ReceivePort();
port.send([msg,response.sendPort]);//可以传普通消息也可以是数组
return response.fist;
}
Isolate.spawnUri
main(){
start();
//执行耗时的任务
newIsolate();
init();
}
start(){
print('启动时间'+ DateTime.now().microsecondsSinceEpoch.toString());
}
newIsolate() async {
print('新线程创建');
ReceivePort r = ReceivePort();
SendPort p = r.sendPort;
//创建新线程
Isolate childIsolate = await Isolate.spawnUri(
Uri(path:"childIsolate.dart"),
['data1','data2','data3'],
p
);
//监听消息
r.listen((message){
print('主线程接收到数据 $message[0]');
if(message[1]==1){
//异步任务正在处理
}else if(message[1]==2){
r.close();//关闭端口
childIsolate.kill(); //释放线程
print('子线程已经释放');
}
})
}
init(){
print('项目初始化')
}
childIsolate.dart文件
import 'dart:isolate';
main(List<String> args,SendPort mainSendPort){
print('新线程接受到的参数:$args');
mainSendPort.send(['开始执行异步操作',0]);
sleep(Duration(1)); //延时一秒
mainSendPort.send(['加载中',1]);
sleep(Duration(1));
mainSendPort.send(['异步任务完成',2]);
}
Future(类似 promise)
- Future 是 Dart 中的类,我们可以通过 Future 实例,凤凰钻杆一些异步任务
- Future 的含义是未来,未来要执行的一些任务,我们可以放到 Future 中
- Future 有三种状态
- 未完成(Uncompleted)
- 已完成,并返回数据(Completed with data)
- 已完成,但返回报错(Completed with error)
获取 Future 实例
- 自动返回
- final myFuture = http.get();
- 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
main(){
//创建Future 实例
final f = new Future((){//new 关键字可以省略
print('Create the future');
print 123;
});
print(f);//Instance of 'Future<int>'
f.then((value)=>print(value));
print('Done with main');
}
main(){
//创建Future 实例
final f = Future.delayed(
Duration(seconds:2),//延时两秒
(){
print 123;
throw Error();
}
).then(value){//Future.delayed
print(value);
}).catchError((err){
print(err);
},test:(error)=>error.runtimeType==String,//查看到报错的详细信息
).whenComplete((){
print('All Completed');
});
}
Future 执行顺序
- Future 默认是一个异步任务,会被丢弃到时间队列(event queue)中
- Future.sync()
- 同步任务,同步执行(不会被丢到异步队列中)
- Future.microtask()
- 微任务,会丢到 microtask queue 中,优先级比时间任务高
- Future.value(val)
- val 是常量(等同于 microtask)
- val 是异步(按照异步逻辑处理)
main(){
print('start');
Future(()=>print('Future() task'));//异步 event queue
Future.sync(()=>print('Future.sync() task'));// 同步
Future.value(Future(()=>print('任务')));//如果value后面的值是异步则按照异步的逻辑处理
Future.microtask(()=>print('Future.microtask() task'));//微任务 microtask queue
Future.value('Futurevalue() const task').then((value)=>print(value));//如果value后面的值 是常量 那么Future.value创建的是微任务
print('end');
}
Future 多任务
- Future.any(futures)
- 返回最先完成的 Future 结果
- Future.wait(futures)
- 等待所有 Future 执行完成,并手机所有 Future 的返回结果
- Future.doWhile(action)
- 按照条件便利执行多个 Future
- Future.forEach(elements,action)
- 遍历一个给定的集合,根据集合元素执行多个 Future
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('最快的'+value.toString()));
print('end');
}
main(){
//等待所有异步任务完成
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.toString());
})
}
main(){
var i = 0;
Future.doWhile((){
i++;
return Future.delayed(Duration(seconds:2),(){
print('Future.doWhile() $i 当前时间:'+ DateTime.now().microsecondsSinceEpoch.toString());
return i<6;
}).then(value){
print(value);
return value;
});
}).then((value){
print('Future.doWhile() then:' + value.toString());
});
}
main(){
Future.forEach([1,2,3],(element){
return Future.delayed(Duration(seconds:2),(){
print('当前元素:$element');
return element.toString()+'_AAA';
}).then((value){
print('处理后的结果 $value');
});
})
}
FutureBuilder
- FutureBuilder 是 Fluter SDK 中提供的异步组件
- FutureBuilder 是一个类,接受 Future 数据,并将数据渲染成界面
- import 'package:flutter/material.dart';
- FutureBuilder 中,有三个属性
- future
- initialData
- builder(context,snapshot)
FutureBuilder-snapshot
- snapshot.connectionState
- ConnectionState.none(未连接异步任务)
- ConnectionState.waiting(链接异步任务,等待交互)
- ConnectionState.active(正在交互)
- ConnectionState.done(异步任务完成)
- snapshot.hasData(Completed with data)
- snapshot.data
- snapshot.hasError(Completed with error)

Stream
- Stream 是 Dart 中的异步数据流,可以连续不断的返回多个数据
- Future 是异步,但是只返回一个值
- Stream 也是异步,可以返回多个值(数据流)
- Stream 相关的 API
- 通过 listen 进行数据监听
- 通过 error 接收失败状态
- 通过 done 来接受结束状态
Stream 类型
- Single-Subscription(单一订阅)
- 数据流只能被 listen 一次(listen 多次会报错)
- StreamController().stream
- Stream stream = Stream.fromIterable(data)
- Broadcast(广播)
- 数据流可以被 listen 多次
- StreamController<int>.broadcast();
- stream.asBroadcastStream()
import 'dart:async';
main(){
//创建单一订阅数据流
final StreamController controller = StreamController();
//第一次监听
conroller.stream.listen((event){
print('Data is $event')
});
//给数据流添加数据
controller.sink.add('abc');
controller.sink.add('123');
}
广播流
import 'dart:async';
main(){
//创建广播流
StreamController controller = StreamController.broadcast();
//第一次监听
conroller.stream.listen((event){
print('Data is $event')
});
controller.sink.add('abc');
//第二次监听
conroller.stream.listen((event){
print('Data2 is $event')
});
//给数据流添加数据
controller.sink.add('123');
}
创建 Stream 实例
- StreamController 类
- sink
- stream
- Stream 类
- Stream.fromFuture()
- Stream.fromFutures()
- Stream.fromIterable()
- Stream.periodic()

Stream.fromFuture
Future<String> getData(){
return Future.delayed(Duration(seconds:2),(){
return '当前时间 ${DateTime.now()}';
})
}
main(){
Stream.fromFuture(getData()).listen((event){
print('Stream.fromFuture: $event');
}).onDone((){
print('Stream.fromFuture done');
})
}
Stream.fromFutures
Future<String> getData(){
return Future.delayed(Duration(seconds:2),(){
return '当前时间 ${DateTime.now()}';
})
}
main(){
var data = [getData(),getData()];
Stream.fromFutures(data).listen((event){
print('Stream.fromFuture: $event');
}).onDone((){
print('Stream.fromFuture done');
})
}
Stream.fromIterable
Future<String> getData(){
return Future.delayed(Duration(seconds:2),(){
return '当前时间 ${DateTime.now()}';
})
}
main(){
var data = [1,2,'hello',true,null];
Stream.fromIterable(data).listen((event){
print('Stream.fromFuture: $event');
}).onDone((){
print('Stream.fromFuture done');
})
}
Stream.periodic
main(){
Duration interval = Duration(seconds:1);
Stream<int> stream = Stream<int>.periodic(interval);
//如果不设置第二个参数 默认返回null
stream.listen((event){
print('Stream.periodic:$event');
}).onDone((){
print('Stream.periodic done');
});
}
main(){
Duration interval = Duration(seconds:1);
Stream<int> stream = Stream<int>.periodic(interval,(data)=>data);
//如果设置第二个参数 默认返回具体数据
stream.take(5).listen((event){//只拉五条数据
print('Stream.periodic:$event');
}).onDone((){
print('Stream.periodic done');
});
}
操作 Stream
- take()|takeWhile()
- where()
- distinct()
- skip()|skipWhile()
- map() //跟 js 的 map 一样
- toSet() |toList() |toString()
- length |first|last take
main(){
Duration interval = Duration(seconds:1);
Stream<int> streamData = Stream<int>.periodic(interval,(data)=>data);
streamData.take(5).listen((event){
print('Stream.periodic-> $event');
}).onDone((){
print('Stream.periodic-> done 结束');
});
}
takeWhile
main(){
Duration interval = Duration(seconds:1);
Stream<int> streamData = Stream<int>.periodic(interval,(data)=>data);
streamData.takeWhile((element){
print('Stream.periodic.takeWhile-> $element');
return element<=3;
}).listen((event){
print('Stream.periodic-> $event');
}).onDone((){
print('Stream.periodic->done 结束')
});
}
where
main(){
Stream<int> streamData = Stream<int>.periodic(interval,(data)=>data);
streamData.takeWhile((element){
print('takeWhile->$element');
return element <= 5;
}).where((data){
print('where-> $data');
return data %2 ==0;//返回偶数
}).listen((event){
print('--$event');
}).onDone((){
print('onDone 结束');
})
}
distinct
main(){
var data = [1,2,'a','a',true,true];
Stream.fromIterable(data).distinct()//去掉与前一个相同的数据
.listen((event){
print('Stream.fromIterable->$event');
}).onDone(()=>print('Stream.fromIterable->done结束'));
}
skip
main(){
Duration interval = Duration(seconds:1);
Stream<int> streamData = Stream<int>.periodic(interval,(data)=>data);
streamData.takeWhile((element){
print('takeWhile:$element');
return element <=6;
}).skip(2).listen((event){
print('-- $vent');
}).onDone((){
print('onDone 结束');
});
}
map
main(){
Stream<int> streamData = Stream<int>.periodic(interval,(data)=>data+1);
streamData.takeWhile((element){
return element<=3;
}).map((event){
print('map-> $event ->${event*100}');
return event * 100;
}).listen((event){
print('listen->$event');
}).onDone((){
print('Done 结束');
});
}
expand
main(){
Stream<int> streamData = Stream<int>.periodic(interval,(data)=>data+1);
streamData.takeWhile((element){
return element<=3;
}).expand((element){
print('map-> $element->${element*100}');
return [element,element*10,element*100];
}).listen((event){
print('listen->$event');
}).onDone((){
print('Done 结束');
});
}




