Fluter基础巩固之Dart语言详解<三>
继续Dart语言的学习,这次过后下次就进入全新的Flutter的学习了,小小的激动。。
操作符重载:
C++中也有,咱们来看一下在Dart中是如何来实现的:
比较简单。
异步【重要!】:
async和await:
- await关键字必须在async函数内部使用。
- await表达式可以使用多次。
看着很自然,接下来再来改造一下,就变得不太好理解了。。
这是为啥呢?下面来剖析一下:
背后其实有一个事件队列,其中main()的执行总是从上往下顺序执行的,当遇到await时,则会将方法添加到队列中,也就是:
此时会将getStr()添加到事件队列中,然后并返回Future,此时的:
然后又加到main()的主流程继续往下执行了,所以:
当整个main()方法都执行完之后,最后再来执行:
有点难理解,为了加深其理解,下面进一步再改造:
好,下面再来分析一下:
然后main()流程往下执行完,所以:
接着再执行:
而此时返回main()由于已经没有代码了,所以最后则将剩下的给执行完了,如下:
这块不是很好理解,但是必须得要了解,因为在未来实际项目中异步会大量用到。
then,catchError,whenComplete:
- 如果需要监听“完毕”这个状态,那么用whenComplete,需要监听“成功”这个状态,用then,需要监听“失败”这个状态,用catchError。
- 如果重写了test方法,test返回true就可以在catchError的onError方法里捕获到异常,如果test返回false,就把该异常继续抛出而不会在catchError方法里被捕获,如果不写test默认实现一个返回true的test方法
咱们来试一下:
咱们也可以catchError一下:
然后看一下catchError的源码:
咱们来使用一下:
Event-Looper:
- 一个消息循环的职责就是不断从消息队列中取出消息并处理他们直到消息队列为空。
- 消息队列中的消息可能来自用户输入,文件I/O消息,定时器等。例如上图的消息队列就包含了定时器消息和用户输入消息。
- Dart中的Main Isolate只有一个Event Looper,但是存在两个Event Queue: Event Queue以及Microtask Queue。
说到Looper就想到了Android中的Looper了,基本上差不多的意思,看一个示例图:
Event-Queue和Microtask Queue:
- 优先全部执行完Microtask Queue中的Event。
- 直到Microtask Queue为空时,才会执行Event Queue中的Event。
- 当Event Looper正在处理Microtask Queue中的Event时候,Event Queue中的Event就停止了处理了,此时App不能绘制任何图形,不能处理任何鼠标点击,不能处理文件IO等等。
- 绘制图形,处理鼠标点击,处理文件IO等都是在Event Queue里完成的。
看一下示意图:
任务调度:
- 优先全部执行完Microtask Queue中的Event。
- 直到Microtask Queue为空时,才会执行Event Queue中的Event。
new Future():
下面来看一个很好理解上面东东的代码:
这代码看着好晕哦。。但是也得硬着头皮来理解,还是很重要的。
接着就是集中来分析一个整个流程。
此时就会将其放到队列当中:
以此类推:
也相继入队:
好,接下来三个Future都调了then,如下:
最后是打印f7:
接着则按入队的顺序来执行,所以此时就执行到:
输出为:
继续:
那此时就会输出了:
接下来则再到:
此时这个Future的then干的事比较多,不要着急,一步步来分析:
所以:
由于f1已经在之前执行过了一次then,执行完了,如下:
所以此时再执行then则会将其放到微队列【如上面所说的Microtask】来:
而微队列的优先级别比较高,如果发现有数据则会立马打印,所以:
此时f2.then()的代码就执行完了:
好,接下来再执行f3.then了:
最后再执行f4:
呃,真的好麻烦呀。。理解了这个程序的运行结果,那上面的各种理论就比较好理解了,所以理解它非常之重要。
scheduleMicrotask():
- 如果可以,尽量将任务放入event队列中。
- 使用Future的then方法或whenComplete方法来指定任务顺序。
- 为了保持你app的可响应性,尽量不要将大计算量的任务放入这两个队列。
- 大计算量的任务放入额外的isolate中。
接下来升级一下程序,再来瞅下:
先直接run一下,省下脑细胞:
面对这样变态的程序,真的是没有一点分析的动力,但是现在还是打基础的阶段,木办法,只能咬牙坚持,下面还是一步步来分析其过程:
所以接下来就是重点分析future相关的执行流程:
而由于微对队的优先级比事件队列的优先级要高,所以立马会打印它,所以:
此时微队列就空了:
接着继续往下分析:
而最底下还有一个微任务,不管怎么样它比Future都要早执行,所以;
此时微队列为:
然后会立马输出,如下:
此时微队列又被清空了,形态现在变为:
接下来再集中来分析事件队列的顺序了:
其事件队列为:
此时要注意啦!!!有then的情况下是需要先将then全部执行完之后,再来执行微任务,不要看到微任务就立马输出,因为微任务是在then中创建的,先要将then执行完,所以输出为:
所以此时的队列情况为:
在then整个都执行完之后,看到微任务队列中还有,则才开始执行它,所以:
此时微队列又空了:
接下来则执行下一个Future:
将其入队:
所以接下来则会按队列先后顺序来执行,所以会输出:
理解了上面两个例子,就对Dart的异步任务就比较了解了。
生成器:
同步生成器:
- 使用sync*,返回的是Iterable对象。
- yield会返回moveNext为true,并等待 moveNext 指令。
- 调用getSyncGenerator立即返回Iterable对象。
- 调用moveNext方法时getSyncGenerator才开始执行。
如何来理解这个程序呢?
直有调用了这个代码才会执行:
为了更加清楚的看到整个执行过程,咱们debug打断点看一下是否如我们所描述的那样:
这个流程真得挺逆天的,完全不是按正常思维来的,记住吧。。
异步生成器:
- 使用async*,返回的是Stream对象。
- yield不用暂停,数据以流的方式一次性推送,通过StreamSubscription进行控制。
- 调用getAsyncGenerator立即返回Stream,只有执行了listen,函数才会开始执行。
- listen返回一个StreamSubscription 对象进行流监听控制。
- 可以使用StreamSubscription对象对数据流进行控制。
看一下代码:
这里debug看一下其执行过程:
反正,我是已经懵逼了,先有个大体认识吧,具体在未来的项目中再来熟悉这样的用法。
递归生成器:
yield* 以指针的方式传递递归对象,而不是整个同步对象。
下面看下代码:
这块了解下用法就成,比较难理解。
隔离-Isolates:
- Dart没有共享内存的并发,没有竞争的可能性所以不需要锁,也就不用担心死锁的问题。
- isolate之间没有共享内存,所以他们之间的通信唯一方式只能是通过Port进行,而且Dart中的消息传递总是异步的。
- isolate神似Thread,但实际上两者有本质的区别。操作系统内的线程之间是可以有共享内存的而isolate没有,这是最为关键的区别。
所有Dart代码都在隔离区内运行,而不是线程。每个隔离区都有自己的内存堆,确保不会从任何其他隔离区访问隔离区的状态。
这里了解一下概念既可,也就是我们在main()其实不是运行在线程当中的,跟Java是不一样的。
元数据(注解):
过一下既可,跟Java类似。
@deprecated:
@override:
自定义:
- 在java中,如果自定义一个注解,需要添加 @Target 作用域注解,@Retention 注解类型注解,添加 @interface,然后定义注解参数。
- 构造方法定义为编译时常量。
只是自定义方式跟Java的是有一些区别的,下面来自定义一下:
注意:上面这个类是一个自定义注解,别以为是一个普通的类哈,接下来可以应用一下它:
至此,整个Dart语言的学习就暂且到这了,真的是很枯燥,但是少了这个内功在Flutter的学习又不行,所以整体把Dart过了一遍,不可能记得住,但是有个整体的入门之后会在未来Flutter的学习走得更加的踏实。。
Fluter基础巩固之Dart语言详解<三>的更多相关文章
- Fluter基础巩固之Dart语言详解<一>
在上一篇https://www.cnblogs.com/webor2006/p/11367345.html中咱们已经搭建好了Flutter的开发环境了,而Flutter的开发语言是选用的dart,那么 ...
- Fluter基础巩固之Dart语言详解<二>
继续学习枯燥的Dart语言语法,目前的耐得住寂寞是为了将来学得“爽”做准备的!!! 异常: Dart 提供了 Exception 和 Error 类型, 以及一些子类型.还可以定义自己的异常类型.但是 ...
- 基础 | batchnorm原理及代码详解
https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...
- Java工程师 基础+实战 完整路线图(详解版)
Java工程师 基础+实战 完整路线图(详解版) Java 基础 Java 是一门纯粹的面向对象的编程语言,所以除了基础语法之外,必须得弄懂它的 oop 特性:封装.继承.多态.此外还有泛型.反射 ...
- Docker 基础技术之 Linux cgroups 详解
PS:欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 推荐大家到公众号阅读,那里阅读体验更好,也沉淀了很多篇干货. 前面两篇 ...
- 原来Github上的README.md文件这么有意思——Markdown语言详解(sublime text2 版本)
一直想学习 Markdown 语言,想起以前读的一篇 赵凯强 的 博客 <原来Github上的README.md文件这么有意思——Markdown语言详解>,该篇博主 使用的是Mac系统, ...
- 《Java基础——break与continue用法详解》
Java基础--break与continue用法详解 1. break语句: 规则: 1. 仅用于循环语句和switch语句当中,用于跳出循环. 2. 当只有一层循环时,则直接跳出循环,不 ...
- JavaEE基础(03):Http请求详解,握手挥手流程简介
本文源码:GitHub·点这里 || GitEE·点这里 一.Http协议简介 1.概念说明 HTTP超文本传输协议,是用于从万维网服务器传输超文本到本地浏览器的传送协议,基于TCP/IP通信协议来传 ...
- Java基础篇(JVM)——字节码详解
这是Java基础篇(JVM)的第一篇文章,本来想先说说Java类加载机制的,后来想想,JVM的作用是加载编译器编译好的字节码,并解释成机器码,那么首先应该了解字节码,然后再谈加载字节码的类加载机制似乎 ...
随机推荐
- Idea中自动生成get,set,toString等方法
https://blog.csdn.net/sinat_41226396/article/details/80770520 自动生成main函数: https://blog.csdn.net/fanr ...
- vue图片放大、缩小、旋转等
用于图片浏览的Vue组件,支持旋转.缩放.翻转等操作,基于viewer.js. 效果: 安装 使用npm命令安装 npm install v-viewer 使用 引入v-viewer及必需的css样式 ...
- 关于被malloc分配内存的指针
例如创建了一个链表指针p并为其malloc()分配了内存,那么这个指针指向的地方其实是有数据的. 你可以把p->data打印出来,会发现是一个随机值 因为只是分配内存而没有指定data的值,所以 ...
- 远程文件传输命令•RHEL8/CentOS8文件上传下载-用例
scp协议 scp [options] [本地用户名@IP地址:]file1 [远程用户名 @IP 地址 :] file2 options: -v 用来显示进度,可以用来查看连接,认证,或是配置错误. ...
- [最新].NET Core ORM 开源项目一览,持续更新
截至2019-05-08共收集27个 .NET Core ORM 开源项目,38个 .NET ORM 开源项目. .NET Core ORM 开源项目收集地址:https://github.com/o ...
- 【操作系统之十四】iptables扩展模块
1.iprange 使用iprange扩展模块可以指定"一段连续的IP地址范围",用于匹配报文的源地址或者目标地址.--src-range:匹配报文的源地址所在范围--dst-ra ...
- 实战django(二)--登录实现记住我
上节初步实现了登录和注册模块,这节我们进一步实现“记住我”功能. 大体功能分为以下模块: 1.在登录时如果勾选记住我,那么就将用户username存进cookie中,跳转到index页面: 2.此时, ...
- Loj #2570. 「ZJOI2017」线段树
Loj #2570. 「ZJOI2017」线段树 题目描述 线段树是九条可怜很喜欢的一个数据结构,它拥有着简单的结构.优秀的复杂度与强大的功能,因此可怜曾经花了很长时间研究线段树的一些性质. 最近可怜 ...
- 喜大普奔,又拍云全新产品 WebSocket 上线啦
作为一款现象级 MMORPG,魔兽世界迎来了自己的 9.0 版本.巧的是,又拍云最近也更新发布了一款产品--WebSocket.你可能会说,两者有个 mao 关系,不着急.我们先来聊聊魔兽世界~ 熟悉 ...
- golang学习笔记----源码文件
GO源码文件