Flutter中如何深入理解异步操作与线程机制?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1418个文字,预计阅读时间需要6分钟。
一、前言:关于多线程与异步 + 关于 Dart关于 Dart,我相信大家都知道 Dart 是一门单线程语言,这里所说的单线程并不是说 Dart 没有多线程或异步功能,而是指 Dart 的所有 API 在默认情况下都是单线程执行的。
一:前言 - 关于多线程与异步
关于 Dart,我相信大家都知道Dart是一门单线程语言,这里说的单线程并不是说Dart没有或着不能使用多线程,而是Dart的所有API默认情况下都是单线程的。但大家也都知道Dart是有办法支持多线程和异步操作的,关于多线程和异步这两个概念是需要我们理清楚的,不能混淆它们的概念,给我们的理解造成困扰。
1、多线程是开辟另外一个线程来处理事件,每个线程都有单独的事件队列,互不影响,这个新线程和当前线程是并列执行的,有的共享数据空间有的不共享(比如Isolate)。
2、异步是不阻塞当前线程,将异步任务和当前线程的任务分开,异步任务后面的任务,不会等待异步任务执行完再执行,而是直接执行,与异步任务的回调没有关系,这样就不影响当前线程的执行,这就叫异步。
接下来我们按照 事件队列 --异步 -- 多线程 这样的顺序整理我们这篇的内容。二:事件队列
这个和iOS比较类似,在Dart的线程中也存在事件循环和消息队列的概念,在Dart的线程中包含一个事件循环以及两个事件队列,我们先说清楚两个事件队列,再来整理它的事件循环或着说是消息循环机制是什么样子的。
1、事件任务队列(Event Queue):负责处理I/O事件、绘制事件、手势事件、接收其他Isolate消息等外部事件,Timer也是事件队列。
2、微任务队列(Microtask Queue)表示一个短时间内就会完成的异步任务。它的优先级最高,高于Event Queue,只要队列中还有任务,就可以一直霸占着事件循环。Microtask Queue添加的任务主要是由Dart内部产生,当然我们也可以自己添加任务到微任务队列中去,但是我们不要在Microtask Queue里面实现耗时操作避免阻塞Event Queue里的UI事件导致卡顿现象。因为微任务队列的优先级要比事件队列的高,所以事件循环每次循环总是先判断微任务队列中是否有任务需要执行,如果有则先执行微任务队列里的任务,执行完毕之后才会执行事件任务队列里的任务,就会造成卡顿。
具体到两个队列的任务怎么创建添加我们后面再提,在了解了这两个队列之后我们再看看Dart的消息循环机制,下面这张图相信大家都见到过:关于事件循环的,需要我们特别留意的:
1、在Microtask不为空的时候,Run nextMicrotask 之后回到最开始,首先判断的是是否还存在微任务,有的话还是优先处理的。
2、在Event不为空的时候,Run next event之后,还是会回去判断是否有Microtask,这点就把前面优先级的问题说的很明白了,这两点需要我们特别留意,在下面我们说完这两个对垒任务的添加之后,我们会写一个稍微比较复杂的方法,仔细的分析一下上面这个事件循环机制。
三:异步
在异步调用中有三个关键词 ,其中async和await/Future是一起使用的,在Dart中可以通过async和await进行一个异步操作,async表示开始一个异步操作,也可以返回一个Future结果。如果没有返回值,则默认返回一个返回值为null的Future,这点也比较容易理解,就像下面的方法,返回值是Future,而我们不写返回return也是可以编译过去的,就是它默认自己返回一个返回值为null的Future。
Future handleMessage(String message) async { print(message); }
Future:默认的Future是异步运行的,也就是把任务放在Future函数体中,这个函数题会被异步执行。
async:异步函数标识,一般与await和Future配合使用。
await:等待异步结果返回,一般加在Future函数体之前,表明后面的代码要等这个Future函数体内的内容执行完在执行,实现同步执行。单独给函数添加async关键字, 没有意义,函数是否是异步的,主要看Future。
注意:Future<T>通过泛型指定类型的异步操作结果(不需要结果可以使用Future<void>)当一个返回Future对象的函数被调用时,函数将被放入队列等待执行并返回一个未完成的Future对象,等函数操作执行完成时,Future对象变为完成并携带一个值或一个错误。也就是说首先Future是个泛型类,可以指定类型。如果没有指定相应类型的话,则Future会在执行动态的推导类型。
结合上面说的这几点,我们写个实际的小例子:class asyncIsolate { Future<HttpClientRequest> dataReqeust() async { var example.org/path?q=dart Future<HttpClientRequest> request = github.com/flutter/flutter.git
Framework • revision 5464c5bac7 (3 weeks ago) • 2022-04-18 09:55:37 -0700
Engine • revision 57d3bac3dd
Tools • Dart 2.16.2 • DevTools 2.9.2
---------------------------------------------------------------
Demo地址:
iOS项目地址:gitee.com/MrRisingSun/iOSMixedFlutter
Flutter项目地址:gitee.com/MrRisingSun/mixed-flutter
---------------------------------------------------------------
## 努力做一个合格的程序员。本文共计1418个文字,预计阅读时间需要6分钟。
一、前言:关于多线程与异步 + 关于 Dart关于 Dart,我相信大家都知道 Dart 是一门单线程语言,这里所说的单线程并不是说 Dart 没有多线程或异步功能,而是指 Dart 的所有 API 在默认情况下都是单线程执行的。
一:前言 - 关于多线程与异步
关于 Dart,我相信大家都知道Dart是一门单线程语言,这里说的单线程并不是说Dart没有或着不能使用多线程,而是Dart的所有API默认情况下都是单线程的。但大家也都知道Dart是有办法支持多线程和异步操作的,关于多线程和异步这两个概念是需要我们理清楚的,不能混淆它们的概念,给我们的理解造成困扰。
1、多线程是开辟另外一个线程来处理事件,每个线程都有单独的事件队列,互不影响,这个新线程和当前线程是并列执行的,有的共享数据空间有的不共享(比如Isolate)。
2、异步是不阻塞当前线程,将异步任务和当前线程的任务分开,异步任务后面的任务,不会等待异步任务执行完再执行,而是直接执行,与异步任务的回调没有关系,这样就不影响当前线程的执行,这就叫异步。
接下来我们按照 事件队列 --异步 -- 多线程 这样的顺序整理我们这篇的内容。二:事件队列
这个和iOS比较类似,在Dart的线程中也存在事件循环和消息队列的概念,在Dart的线程中包含一个事件循环以及两个事件队列,我们先说清楚两个事件队列,再来整理它的事件循环或着说是消息循环机制是什么样子的。
1、事件任务队列(Event Queue):负责处理I/O事件、绘制事件、手势事件、接收其他Isolate消息等外部事件,Timer也是事件队列。
2、微任务队列(Microtask Queue)表示一个短时间内就会完成的异步任务。它的优先级最高,高于Event Queue,只要队列中还有任务,就可以一直霸占着事件循环。Microtask Queue添加的任务主要是由Dart内部产生,当然我们也可以自己添加任务到微任务队列中去,但是我们不要在Microtask Queue里面实现耗时操作避免阻塞Event Queue里的UI事件导致卡顿现象。因为微任务队列的优先级要比事件队列的高,所以事件循环每次循环总是先判断微任务队列中是否有任务需要执行,如果有则先执行微任务队列里的任务,执行完毕之后才会执行事件任务队列里的任务,就会造成卡顿。
具体到两个队列的任务怎么创建添加我们后面再提,在了解了这两个队列之后我们再看看Dart的消息循环机制,下面这张图相信大家都见到过:关于事件循环的,需要我们特别留意的:
1、在Microtask不为空的时候,Run nextMicrotask 之后回到最开始,首先判断的是是否还存在微任务,有的话还是优先处理的。
2、在Event不为空的时候,Run next event之后,还是会回去判断是否有Microtask,这点就把前面优先级的问题说的很明白了,这两点需要我们特别留意,在下面我们说完这两个对垒任务的添加之后,我们会写一个稍微比较复杂的方法,仔细的分析一下上面这个事件循环机制。
三:异步
在异步调用中有三个关键词 ,其中async和await/Future是一起使用的,在Dart中可以通过async和await进行一个异步操作,async表示开始一个异步操作,也可以返回一个Future结果。如果没有返回值,则默认返回一个返回值为null的Future,这点也比较容易理解,就像下面的方法,返回值是Future,而我们不写返回return也是可以编译过去的,就是它默认自己返回一个返回值为null的Future。
Future handleMessage(String message) async { print(message); }
Future:默认的Future是异步运行的,也就是把任务放在Future函数体中,这个函数题会被异步执行。
async:异步函数标识,一般与await和Future配合使用。
await:等待异步结果返回,一般加在Future函数体之前,表明后面的代码要等这个Future函数体内的内容执行完在执行,实现同步执行。单独给函数添加async关键字, 没有意义,函数是否是异步的,主要看Future。
注意:Future<T>通过泛型指定类型的异步操作结果(不需要结果可以使用Future<void>)当一个返回Future对象的函数被调用时,函数将被放入队列等待执行并返回一个未完成的Future对象,等函数操作执行完成时,Future对象变为完成并携带一个值或一个错误。也就是说首先Future是个泛型类,可以指定类型。如果没有指定相应类型的话,则Future会在执行动态的推导类型。
结合上面说的这几点,我们写个实际的小例子:class asyncIsolate { Future<HttpClientRequest> dataReqeust() async { var example.org/path?q=dart Future<HttpClientRequest> request = github.com/flutter/flutter.git
Framework • revision 5464c5bac7 (3 weeks ago) • 2022-04-18 09:55:37 -0700
Engine • revision 57d3bac3dd
Tools • Dart 2.16.2 • DevTools 2.9.2
---------------------------------------------------------------
Demo地址:
iOS项目地址:gitee.com/MrRisingSun/iOSMixedFlutter
Flutter项目地址:gitee.com/MrRisingSun/mixed-flutter
---------------------------------------------------------------
## 努力做一个合格的程序员。
