Dart语法

Dart的历史

Dart 1.0是于2013年11月14日由谷歌发布的,由Lars Bak和Kasper Lund创建。它旨在帮助开发人员构建现代的web和移动应用程序。它涵盖了客户机、服务器和现在的Flutter移动设备。它提供了一系列工具,包括虚拟机、核心库和包管理存储库。

什么是Dart?

-Dart是由谷歌开发的通用的编程语言,它常用于构建web、服务器、桌面和移动应用程序。

-Dart是一种简洁、清晰、基于类的面向对象的语言,它是基于JavaScript的但是结构要比JavaScript要多。

-Dart是一种面向对象的、类定义的、垃圾回收语言。它支持接口、mixin、类对象,具有化泛型、静态类型等。

面向对象

对于面向对象这个概念,相信了解Java的同学对这个概念一定不会陌生。

例如:我们有个 Person Object 他有很多特征和行为。

characteristics: name age height
behaviors: walk eat sleep

这些都是这个 Person Object 的属性。
也就是因为有了这些特征,行为等等才决定了这个人是谁。

那么回到Dart当中,所有的都是对象,那么在就可以可以跟进对象的属性的特征,方法等等来进行编程。

之所以我们在这里又特别强调了一下面向对象的概念,是因为这个概念在Dart语言当中,至关重要!

重要的几个概念

  1. 在Dart语言中,所有的东西都是对象,无论是变量、数字、函数、null 等都是对象,所有的对象都是 Object 类的子类。

  2. Dart语言是强类型编程,一旦确定了类型,那么就不可以改变变量类型,在编译时会进行语法减产,但是Dart允许弱类型语言式的编程。

  3. Dart代码在运行前解析,指定数据类型和编译时常量,可以提高运行速度。

  4. Dart语言的统一入口是 main 函数。

  5. Dart的私有特性是在变量或者函数名前面加上下划线_。

  6. Dart支持 async/await 异步处理。

Dart的部分特性

  1. Dart是AOT(Ahead Of Time)编译的,可编译成快速,可预测的本地代码。

  2. Dart可以JIT(Just In Time)编译,开发周期快,为Flutter热重载提供基础。

  3. Dart可以轻松创建60fps运行的流畅动画和转场。

  4. Dart的声明式编程布局,易于阅读和可视化,不需要单独的声明式布局语言,如:XML,JSX

  5. Dart非常易于学习,具有静态和动态语言,编程人员都熟悉的特性。

Flutter为什么选择使用Dart?

相信,看过上面的内容的小伙伴,多多少少对于Dart有个简单的认识了,那么为什么Flutter为什么采用Dart语言呢?

可以归结为以下的三个方面:

优化内存

Flutter 框架使用函数式流,它重度依赖底层内存分配器对小量的、短生命周期内存分配的有效处理,在缺乏这种特性的语言中Flutter无法有效地工作。

开发者生产效率

Flutter 的一个主要的价值主张就是节省工程资源,开发者通过同一套代码库可以实现iOS和Android两个平台的应用开发工作。使用高产的语言提高了开发效率,也使得Flutter更具吸引力,这对于我们框架团队和开发者都异常重要。 构建Flutter主体的语言和我们提供给用户的是相同的,所以我们需要在100k行代码的基础上保证高效,并且保证不牺牲framework和widgets对读者的可读性。

面向对象

对于Flutter,我们想要一个能够符合Flutter问题域的语言,即创造视觉用户体验,通过面向对象语言构建用户界面框架,业内已经有了几十年的经验。当然我们可以使用非面向对象的语言,这将意味着重复发明轮子来解决几个艰难的问题。此外,大多数的开发者已经拥有面向对象的开发经验,这使得Flutter开发更加易学。

可预期 高性能

通过Flutter,我们想要给开发者赋能,以开发出快速流畅的用户体验。为了达到这一点,我们需要能够在每个动画帧运行大量的代码。这意味着我们需要一种能够同时提供高效和稳定性能的语言,不能有周期性的停顿,否则会造成掉帧。

高效的使用

热重载是Flutter最显著的特性之一,有了这个特性,我们可以快速并且轻松的进行实现、构建UI、添加属性和修复Bug。热重载的加载过程就是通过源代码文件注入在运行的Dart虚拟机当中来工作。

Dart的内置库

包名描述
dart:asynv异步编程,提供Future,Stream类
dart:collection集合
dart:convert不同类型的字符编码解码
dart:coreDart语言核心功能,内置类型
dart:html网页开发用到的库
dart:io文件读写,IO相关
dart:math数字常量以及函数,随机算法等
dart:svg事件和动画矢量图支持

变量和数据类型

变量
命名

在Dart语言当中,定义变量的方式是

dataType viriableName = Initial Valute

这里其实和Java是一样的,不仅如此连命名的方式也和Java相同,都是采用驼峰命名的方式。

声明

在声明的时候,除了基本数据类型之外,还有三种变量的声明。

vardynamicObject

  • var:如果没有初始值的时候,var 可以变成任意类型。

  • dynamic:动态任意类型,编译阶段不检查类型。

  • Object: 动态任意类型,在编译阶段检查类型。

var 的区别:
var 如果有初始值,那么类型会被锁定。

变量的默认值
  1. 没有初始值的变量会自动获取一个默认值 null
  2. 一切皆为对象,对象的默认值是 null
finalconst

表示不可改变

相同点:

  • 声明的类型可以省略
  • 初始化后不能再赋值
  • 不能和 var 同时使用

不同点:

  • 类级别常量,使用 static const
  • const 可使用其他 const 常量的值来初始化其值
  • 使用 const 赋值声明,const 可以省略
  • 可以更改非 final 、非 const 变量的值。即使曾经具有 const
  • const 导致的不可变性是可以传递的
  • 相同的 const 常量不会再内存中重复创建
  • const 需要是编译时常量
基本数据类型

Dart总共又8种基本数据类型。
分别是:

  • Numbers
  • Strings
  • Booleans
  • Lists
  • Maps
  • Sets
  • Runes
  • Symbols
Numbers 数值型

数值型里面有包含了 int 型和 doubule 两种类型,这两种和Java类似,其中 int 是整数型,double64-bit 双精度浮点数,这两种都是 Numbers 类型的子类。

String

Dart字符串是 UTF-16 编码的字符序列。

  1. 可以使用单引号或者双引号来创建字符
    例如:
void main() {
  print("This is a String");
  print('This is also a stirng');
}

这两个是一样的。

  1. 字符串拼接
    例如:
void main() {
  String s1 = "First string.";
  String s2 = "Second string";
  print(s1 + s2);
}
  1. 字符插值
    ${exprsssion} ,如果表达式是一个标识符,可以省略 {},如果表达式的结果为一个对象,Dart会调用对象的 toString() 函数来获取一个字符串。
    例如:
void main() {
  String s1 = "First string.";
  print("String $s1");
}
void main() {
  print("The sum of 1 and 1 equals ${1 + 1}.");
}
  1. 多行显示
    使用双引号创建多行字符
    还可以使用 '"
    例如:
 var s = 'Firtst'
  'Second'
  "Third";
   print(s);

使用三引表示多行字符
例如

 var multilineString = """This is a
   multiline string
   consistiong of
   multiple lines""";
  print(multilineString);
  1. 使用 r 前缀创建“原始raw”字符串
  String s4 ="adbchi\ndfafa";
  print(s4);

  String s5 =r"adbchi\ndfafa";
  print(s5);

输出的结果

I/flutter (17682): adbchi
I/flutter (17682): dfafa
I/flutter (17682): adbchi\ndfafa
Bool

Dart的 bool 和Java类似只有两种类型,一种是 true 一种是 false ,但是,不同的是 bool 对象未初始化的默认值是 null

List

因为在Dart当中,由一切皆为对象的概念,Dart就可以直接打印 list 包含 list 的元素,这点和Java由明显的不同,Java 中直接打印 list 结果是地址值。
例如

 var list = [0, 1, 2, 3, 4, 5, 6];
  print(list);

打印出结果

I/flutter (24300): [0, 1, 2, 3, 4, 5, 6]

-Dart中 List 的下标索引和Java一样都是从 0 开始。
-Dart中 List 也支持泛型,这点和Java一样,同时还可以进行泛型的判断。

 var list1 = List<String>();
 print(list1 is List<String>);
 输出:
 true

有增删改查的操作,支持倒叙,自带顺序,洗牌,可以使用 + 将两个 List 合并。
例如

  var list = [0, 1, 2, 3, 4, 5, 6];
  print(list);
  var list2 = [7,8,9,10,11];

  print(list+list2);
   输出:
  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Set

Dart里面的 Set 和Java类似,也是不能存放重复的元素。

两种初始化方式
Set 有两种初始化方式

var setName = <dataType>{}
Set<dataType> setName ={}

大部分操作是和Java类似的
不同的地方:

  • difference:返回 set1 集合里面有但是 set2 里面没有的元素集合
 Set<String> set1 = {"1","2","3","4","5"};
 Set<String> set2 = {"1","2","3"};
 print(set1.difference(set2));
 输出:
 {4, 5}
- `intersection`:返回 `set1` 和 `set2` 的交集
Set<String> set1 = {"1","2","3","4","5"};
Set<String> set2 = {"1","2","3"};
print(set1.intersection(set2));
 输出:
{1, 2, 3}
  • union:返回 set1set2 的并集
 Set<String> set1 = {"1","2","3","4","5"};
  Set<String> set2 = {"1","2","3"};
  print(set1.union(set2));
   输出:
{1, 2, 3, 4, 5}
  • retainAll:set1 只保留某些元素(要保留的元素要在原 set 中存在)
Map

和Java类似

Runes

Runes 再Dart当中是字符的 UTF-32 的编码

Main(){
  Runes runes = new Runes('\u{1f605} \u6211‘);
  var str1 = String.fromCharCodes(runes);  
  print(str1);
}
Symbol

Symbol 标识符,主要是反射的作用,现在再 mirrors 模块已经被移除了。

函数

定义

总体来说,和Java类似。
其他几个特单:

  • 可在函数内定义
  • 定义函数时可以省略类型
  • 支持缩写语法=>
int add(int a, int b) => a + b;
可选参数
  • 可以选择命名参数
  • 可以选择位置参数
  • 可以添加默认参数
printer(num n,{String s1, String s2}) { 
  print(n); 
  print(s1); 
  print(s2);
}

main() {
  printer(75, s1: 'hello');
}
printer(num n,{String s1, String s2}) { 
  print(n); 
  print(s1); 
  print(s2);
}

main() {
  printer(75);
}
printer(num n,{String s1, String s2}) { 
  print(n); 
  print(s1); 
  print(s2);
}

main() {
  printer(75, s1: 'hello', s2: 'there');
}
String mysteryMessage(String who, [String what, String where]){
  var message = '$who';
  if(what != null && where == null){
    message = '$message said $what';
  } else if (where != null){
    message = '$message said $what at $where';
  }
  return message;
}

main() {
  var result = mysteryMessage('Billy', 'howdy', 'the ranch');
  print(result);
}
匿名函数
  • 可以赋值给变量,通过变量调用
  • 可以在其他函数当中直接调用或者传递给其他函数
//匿名函数
  //赋值给变量
  //无参匿名函数
  var anonFunc1 = () => print('无参匿名函数');
  anonFunc1();

  //有参匿名函数
  var anonFunc = (name) => 'I am $name';
  print(anonFunc('damon'));

  //通过()调用,不推荐
//  (()=>print('不推荐'))();

  //匿名函数传参
  List test(List list, String func(str)) {
    for (var i = 0; i < list.length; i++) {
      list[i] = func(list[i]);
    }
    return list;
  }

  var list = ['d', 'a', 'm', 'o', 'n'];
  print(test(list, (str) => str * 2)); //String * int, Dart和Python可以这样用

  //List.forEach()就用的匿名函数
  List list1 = [11, 12, 13];
  list1.forEach((item) => print('$item'));

  //返回Function对象(闭包)
  Function makeAddFunc(int x) {
    x++;
    return (int y) => x + y;
  }

  var addFunc = makeAddFunc(2);
  print(addFunc(3));

  // 函数别名
  MyFunc myFunc;
  //可以指向任何同签名的函数
  myFunc = subtsract;
  myFunc(4, 2);
  myFunc = divide;
  myFunc(4, 2);
  //typedef 作为参数传递给函数
  calculator(4, 2, subtsract);
}

//函数别名
typedef MyFunc(int a, int b);
//根据MyFunc相同的函数签名定义两个函数
subtsract(int a, int b) {
  print('subtsract: ${a - b}');
}

divide(int a, int b) {
  print('divide: ${a / b}');
}
//typedef 也可以作为参数传递给函数
calculator(int a, int b, MyFunc func) {
  func(a, b);
}

逻辑运算

操作符

操作符大部分也和Java相同。

描述操作符
后缀操作expr++ expr-- () [] . ?.
前缀操作-expr !expr ~expr ++expr --expr
乘除* / % ~/
加减±
位移<< >>
按位与&
按位异或^
按位或|
类型操作>= > <= < as is is!
相等== !=
逻辑与&&
逻辑或||
是否为空??
三目运算expr1 ? expr2 : expr3
级联..
赋值*= /= ~/= %= += -=<<= >>= &= ^= |= ??=

标红的是不同的,下面着重介绍一下。

?.

条件成员访问 和 . 类似,但是左边的操作对象不能为 null,例如 foo?.bar 如果 foonull 则返回 null,否则返回 bar 成员。

 String a;
print(a?.length);
输出null

 String a="aaa";
print(a?.length);
输出 3
~/

取商操作符
被除数 ÷ 除数 = 商 … 余数A ~/ B = C,这个 C 就是商。相当于Java里的 /

asisis!

类型判定操作
类型判定操作符:asisis!在运行时判定对象类型

 //as 类型转换
  num iNum = 1;
  num dNum = 1.0;
  int i = iNum as int;
  double d = dNum as double;
  print([i, d]);

//  String s = iNum as String;

  //is 如果对象是指定的类型返回 True
  print(iNum is int);
  Child child;
  Child child1 = new Child();
  print(child is Parent); //child is Null
  print(child1 is Parent);

  //is! 如果对象是指定的类型返回 False
  print(iNum is! int);

级联操作符
连续调用多个函数以及访问成员变量。
两个点的级联语法不是一个操作符。 只是一个Dart特殊语法。

 StringBuffer sb = new StringBuffer();
  sb
    ..write('dongnao')
    ..write('flutter')
    ..write('\n')
    ..writeln('damon');

流程控制语句

  • if else
  • forforEachfor-in
  • whiledo-while
  • breakcontinue
  • switch case
  • assert

大部分使用方法都是和Java相同的。
不同的有

  • for-in
  var colorList = ['black','red','yellow'];
  for(var i in colorList){
    print(i);
  }
  输出:
  I/flutter (31601): black
  I/flutter (31601): red
  I/flutter (31601): yellow
  • assert
    断言,它可以为代码执行设置条件,用于bool条件为false时中断正常的运行。
    assert(condition,optional,message)
  var variable;
  print(variable);
  assert(variable!=null);
  variable = 6;
  print(variable);
  输出:
   [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: 'package:flutter_app/main.dart': Failed assertion: line 50 pos 10: 'variable!=null': is not true.

异常

不管是Java语言还是Dart语言,都有异常,以及异常的捕获,但是不同的是Dart中的异常都是非检查异常,方法可以不声明可能抛出的异常,也不要求捕获任何异常。

Dart提供了 ExceptionError 类型以及一些子类型来定义异常。不过,还可以自定义异常,只要抛出非空对象作为异常即可,不要求必须是 ExceptionError 对象,但是一般来说都是抛出 ExceptionError 类型。

接下来我们详细介绍一下。

Exception 类型
名称说明
DeferredLoadException延迟加载异常
FormatException格式异常
IntegerDivisionByZeroException整数除零异常
IOExceptionIO异常
IsolateSpawnException隔离产生异常
TimeoutException超时异常
Error 类型
名称说明
AbstractClassinstantiationError抽象类实例化错误
ArgumentError参数错误
AssertionError断言错误
AsyncError异步错误
CastErrorCast 错误
ConcurrentModificationError并发修改错误
CyclicinitializationError周期初始错误
FallThroughErrorFall Through 错误
JsonUnsupportedObjectErrorjson 不支持错误
NoSuchMethodError没有这个方法错误
NullThrownErrorNull 错误
OutOfMemoryError内存溢出错误
RemoteError远程错误
StackOverflowError堆栈溢出错误
StateError状态错误
UnimplementedError未实现的错误
UnsupportedError不支持错误
异常抛出

异常的抛出和Java还是很相像的。

  //抛出Exception对象
  throw new FormatException('格式异常');

  //抛出Error对象
  throw new NullThrownError();

  //抛出任意非null对象
//  throw '这是一个异常';
异常捕获
try {
    throw new NullThrownError();
    // throw new OutOfMemoryError();
  } on OutOfMemoryError {
    // on 指定异常类型
    print('没有内存了');
    // rethrow; //把捕获的异常给 重新抛出
  } on Error {
    //捕获Error类型
    print('Unknown error catched');
  } on Exception catch (e) {
    //捕获Exception类型
    print('Unknown exception catched');
  } catch (e, s) {
    //catch() 可以带有一个或者两个参数, 第一个参数为抛出的异常对象, 第二个为StackTrace对象堆栈信息
    print(e);
    print(s);
  }

类的概念和Java当中类似。
但是也有很大的区别。

类的构造
//java中写法
class P {
  double x;
  double y;

  P(int x, int y) {
    this.x = x;
    this.y = y;
  }
}

//dart建议写法
class P {
  num x;
  num y;
  Point(this.x, this.y);
}
重定向构造函数
class P { 
  num x; 
  num y; 

  Point(this.x, this.y); 

  //重定向构造函数,使用冒号调用其他构造函数
  P.alongXAxis(num x) : this(x, 0);
}
类的Get和Set方法
class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  num get right => left + width;
  set right(num value) => left = value - width;
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
}
mixins

Mixins 是Dart里面的一个全新概念,简单来说,用来复用多个类之间的代码,减少耦合,换句话来说,可以从中扩展方法(或变量)而不扩展类。

下面具体举例说明一下:

例如,我们有这么一个职业关系图:

工作者
工程师 教师
软件工程师 建筑工程师 美术教师 IT教师

从图中可以梳理出以下关系:

  • 工程师类目,有软件工程师和建筑工程师等,他们共同点都是工程师。
  • 教师类目有美术教师,IT教师等,他们共同点都是教师。

如果我们用Java来实现的话

//工作者
abstract class Worker {
    public abstract void doWork();//工作者需要工作
}

//工程师
class Engineer extends Worker {
    @Override
    public void doWork() {
        System.out.println("工程师在工作");
    }
}

//教师
class Teacher extends Worker {
    @Override
    public void doWork() {
        System.out.println("教师在教学");
    }
}

//软件工程师
class SoftwareEngineer extends Engineer {}

//建筑工程师
class BuildingEngineer extends Engineer {}

//美术教师
class ArtTeacher extends Teacher {}

//IT教师
class ITTeacher extends Teacher {}

如果用Dart来实现

//工作者
abstract class Worker {
  void doWork();//工作者需要工作
}

//工程师
class Engineer extends Worker {
  void doWork() {
    print('工程师在工作');
  }
}

//教师
class Teacher extends Worker {
  void doWork() {
    print('教师在教学');
  }
}

//软件工程师
class SoftwareEngineer extends Engineer {}

//建筑工程师
class BuildingEngineer extends Engineer {}

//美术教师
class ArtTeacher extends Teacher {}

//IT教师
class ITTeacher extends Teacher {}

从以上来看,似乎Java和Dart没有什么特别大的区别,因为Dart也是单继承。

下面,我们再把场景丰富一下。

工作者
工程师 教师
软件工程师(软件设计 修电脑) 建筑工程师(手绘) 美术教师(手绘 书法) IT教师(修电脑)

通过图形或表格可以看出,软件工程师和IT教师都具备修电脑的能力,建筑工程师和美术教师都具备手绘的能力,但是这些能力都是他们特有的,不是工程师或者教师具备的能力,所以不能在他们的父类中实现。

如果使用 Java,那么我们自然就想到了使用 interface

interface CanFixComputer {
    void fixComputer();
}

interface CanDesignSoftware {
    void designSoftware();
}

//软件工程师
class SoftwareEngineer extends Engineer implements CanFixComputer, CanDesignSoftware {

    @Override
    public void fixComputer() {
        System.out.println("修电脑");
    }

    @Override
    public void designSoftware() {
        System.out.println("设计软件");
    }
}

//IT教师
class ITTeacher extends Teacher implements CanFixComputer {

    @Override
    public void fixComputer() {
        System.out.println("修电脑");
    }
}

但是,我们知道Dart当中没有 interface 的概念,但并不意味着这门语言没有接口,事实上,Dart任何一个类都是接口,你可以实现任何一个类,只需要重写那个类里面的所有具体方法。

如果要用Dart来实现的化,只需要将 interface 修改成 abstract class

但是我们发现,fixComputer 这个接口被继承了两次,并且两次的实现都是一样的,这里就出现了代码重复和冗余的问题。怎么办呢?在Java中我们有接口的 default 实现来解决这个问题(这是一个 Java8 出现的不得已的方案。)

但是,有了 mixins 之后,这件事就变得不那么难了。

abstract class CanFixComputer {
  void fixComputer() {
    print('修电脑');
  }
}

abstract class CanDesignSoftware {
  void designSoftware() {
    print('设计软件');
  }
}

//软件工程师
class SoftwareEngineer extends Engineer
    with CanFixComputer, CanDesignSoftware {

}

//IT教师
class ITTeacher extends Teacher with CanFixComputer {

}

main() {
  ITTeacher itTeacher = new ITTeacher();
  itTeacher.doWork();
  itTeacher.fixComputer();
  SoftwareEngineer softwareEngineer = new SoftwareEngineer();
  softwareEngineer.doWork();
  softwareEngineer.fixComputer();
  softwareEngineer.designSoftware();
}

通过以上代码,我们可以看到这里不用 ·implements,更不是 extends,而是 with`。

每个具有某项特性的类不再需要具体去实现同样的功能,接口是没法实现功能的,而通过继承的方式虽然能实现功能,但已经有父类,同时不是一个父类,又不能多继承,所以这个时候,Dart的 Mixin 机制就比Java的接口会高效,开发上层的只需要关心当前需要什么特性,而开发功能模块的关心具体要实现什么功能。

关于顺序的理解

既然是 with ,那应该也会有顺序的区别。

class First {
  void doPrint() {
    print('First');
  }
}

class Second {
  void doPrint() {
    print('Second');
  }
}

class Father {
  void doPrint() {
    print('Father');
  }
}

class Son1 extends Father with First,Second {
  void doPrint() {
    print('Son1');
  }
}

class Son2 extends Father with First implements Second {
  void doPrint() {
    print('Son2');
  }
}

main() {
  Son1 son1 = new Son1();
  son1.doPrint();
  Son2 son2 = new Son2();
  son2.doPrint();
}

输出的内容是:

Son1
Son2

通过这里,我们可以看到
可以看到,无论是 extendsimplements 还是 mixin,优先级最高的是在具体类中的方法。

下一个例子:

class First {
  void doPrint() {
    print('First');
  }
}

class Second {
  void doPrint() {
    print('Second');
  }
}

class Father {
  void doPrint() {
    print('Father');
  }
}

class Son1 extends Father with First,Second {

}

class Son2 extends Father with First implements Second {

}

main() {
  Son1 son1 = new Son1();
  son1.doPrint();
  Son2 son2 = new Son2();
  son2.doPrint();
}

输出的结果:

Second
First

其实在 Son2implements 只是说要实现他的 doPrint() 方法,这个时候其实具体实现是 FirstMixin 了具体实现。
Mixin 的具体顺序也是可以从代码倒过来看的,最后 mixin 的优先级是最高的。

泛型

在Dart当中,有很多的容器对象,在创建对象时都可以定义泛型类型,这一点和Java是一样的。
例如:

 var list = List<String>();
  list.add('aaa');
  list.add('bbb');
  list.add('ccc');
  print(list);

  var map = Map<int, String>();
  map[1] = 'aaaa';
  map[2] = 'bbbb';
  map[3] = 'cccc';
  print(map);

和Java的区别

Java 中的泛型信息是编译时的,泛型信息在运行时是不存在的。

Dart的泛型类型是固化的,在运行时也有可以判断的具体类型。

异步

Future

说到异步就不得不说到 Future

Future 与JavaScript中的 Promise 非常相似,表示一个异步操作的最终完成(或失败)及其结果值的表示。简单来说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个 Future 只会对应一个结果,要么成功,要么失败。

因为Flutter返回的都是一个 Fluter 对象,自然就可以采用链式方法。

  1. Future.then 任务执行完后的子任务
  2. Future.delayed 延迟执行
  3. Future.catchError 如果异步任务发生错误,我们可以在 catchError 中捕获错误。
  4. Future.whenComplete 完成的时候调用。
  5. Future.wait 等待多个异步任务都执行结束后才进行一些操作。
async/await

如果业务逻辑中有大量异步依赖的情况,将会出现上面这种在回调里面套回调的情况,过多的嵌套会导致的代码可读性下降以及出错率提高,并且非常难维护,这个问题被形象的称为回调地狱(Callback Hell)。

这个问题在JS当中十分的突出,Dart几乎是同样的问题,然后把相关方法平移过来。所以功能和用法也几乎是相同的。

async 用来表示函数是异步的,定义的函数会返回一个 Future 对象,可以使用 then 方法添加回调函数。
await 后面是一个 Future,表示等待该异步任务完成,异步完成后才会往下走;await 必须出现在 async 函数内部。

  • 只有 async 方法才能使用 await 关键字调用方法
  • 如果调用别的 async 方法必须使用 await 关键字。
Stream

Stream 也是用于接收异步事件数据,和 Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。

Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(new Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(new Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(new Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});

输出

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3
Isolates-隔离

所有Dart代码都在隔离区内运行,而不是线程。每个隔离区都有自己的内存堆,确保不会从任何其他隔离区访问隔离区的状态。

  • 20
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值