Dart 语法

7,135 阅读21分钟

Dart我们有不得不学的理由,因为有Flutter这尊大神在啊,但是像有的大神这样潇洒,现阶段我还做不到

如果您熟悉面向对象和基本编程概念(如变量、循环和条件控制),则可以完成本教程,您无需要了解Dart或拥有移动开发的经验

膜拜大神...... 初上Dart有种似曾相识的感觉,那是因为现在高阶语言基本趋同,Dart又是融合强类型语言和弱类型语言,所以还是不能直接跳过,要不然很多代码其实也是不怎么清楚的。再者对我自己来说,若是不把Dart系统的走一遍,还是会有朦胧感的,这样很不舒服的

本文重在给初次接触Dart的朋友提供帮助,内容涵盖基础语法,但是Dart的多线程、异步不在本文之列,那是下一篇的内容。同时呢自己上手操作下、再写一遍笔记,这样记得清楚,更是为以后着想,人过留名,雁过留声,我们学完了不写博客怎么证明我们学过了,以后忘了怎么办,那就是白学了嘛,希望大家都自己做笔记写博客、写文章

我写的很随自己的意思,大家看不惯的话请看下面写的很标准的:


Dart 历史和简述

在学习一个语言前,我们了解下该语言的历史,往往都会有一些会心一笑的收获。我们再看一下该语言的简介,总是会让我们后面的学习简单不少

本段摘自:Flutter基础(三)Dart快速入门

Dart 历史

Dart 是谷歌开发的计算机编程语言,亮相于2011年10月,最新的版本是Dart2。Dart诞生的原因是谷歌的工程师出于对JavaScript的不满,诞生的初期也赢得了部分前端开发者的青睐。但是这时JavaScript借着NodeJS火了起来,在前端、后端、移动端无孔不入,Dart就渐渐被人遗忘了,可见Dart本身是具有很强的实力的,只是不大走运

谷歌并没有放弃Dart,不遗余力的推广Dart:谷歌的Angular提供了Dart版本,指定Dart为新系统Fuchsia的官方开发语言,Dart为移动UI框架Flutter的开发语言,因此Dart又重新回到了人们的视野中。 Dart通常情况下运行在DartVM上,但是在特定情况下它也可以编译成本地代码运行在硬件上,比如Flutter会将代码编译成指定平台的本地代码来提高性能

Dart 主要特性:

  • 执行速度快 Dart是AOT(Ahead Of Time)编译的,可以编译成快速的、可预测的本地代码,这使得Flutter几乎都可以使用Dart来编写。也可以采用JIT(Just In Time)编译。
  • 易于移植 Dart可编译成ARM和X86代码,这样Dart可以在Android、iOS和其他地方运行。 容易上手,Dart充分吸收了高级语言特性,如果你已经熟悉C++、C、Java,可以在短短几天内用Dart来开发
  • 易于阅读 Dart使Flutter不需要单独的声明式布局语言(XML或JSX),或者单独的可视化界面构建器,这是因为Dart的声明式编程布局易于阅读。
  • 避免抢占式调度 Dart可以在没有锁的情况下进行对象分配和垃圾回收,和JavaScript一样,Dart避免了抢占式调度和共享内存,因此不需要锁。

Dart 简述:

  • 在Dart中,一切都是对象,每个对象都是一个类的实例,所有对象都继承自Object。
  • Dart在运行前解析所有的代码,指定数据类型和编译时常量,可以使代码运行的更快。
  • 与Java不同,Dart不具备关键字public、protected、private。如果一个标识符以下划线_开始,那么它和它的库都是私有的。
  • Dart支持顶级的函数如main(),也支持类或对象的静态和实例方法,还可以在函数内部创建函数。
  • Dart支持顶级的变量,也支持类或对象的静态变量和实例变量,实例变量有时称为字段或属性。
  • Dart支持泛型类型,如List(整数列表)或List(任何类型的对象列表)。
  • Dart工具可以报告两种问题:警告和错误。警告只是说明代码可能无法正常工作,但不会阻止程序执行。错误可以是编译时或运行时的。编译时错误会阻止代码执行; 运行时错误会导致代码执行时报出异常。

Dart 关键字列表:


Dart 特性

网上很多文章都说 Dart 在java 的基础上融会了高级语言的特性,但是我想说 java 最新版本就没有吗?所以这样说等于没说

要我说 Dart = java + kotlin,要是您接触过 python,那么 Dart = java + python 才是最恰当的,在 Dart 中您即可以编写传统 java 风格的代码,也可以编写类似 python 风格的代码,下面我尽量给大家展示出来 Dart 在那些方面像 python

1. 像 python 的地方

  • 1.1 Dart 支持库形式开发 用过python的同学都知道是怎么回事,在java里我们创建一个class文件必须要在该文件内创建一个和该文件同名的类
public class Name {
    ......
}

但是Dart允许我们在Dart文件种不创建类,直接写属性、写方法,然后以库的方式给别人使用

DartLib 代码:

var name = "NAME";

void function1() {
  print(name);
}

void function2() {
  print("BBB");
}

以库的形式导入使用

import 'package:flutter_app4/DartLib.dart' as Lib;

void test(){
  Lib.name = "FUN";
  Lib.function1();
}
  • 1.2 Dart 允许大家像 python 那样声明变量
var book = Book("AA", 18);
  • 1.3 Dart 可以像 python 一样,方法声明时返回值可写可不写,编译器会自动判断返回类型的
  sum( var num1){
    return num1 + 10;
  }
  • 1.4 Dart 和 python 最大的区别:就是 Dart 不能像 python 那样可以处处省略参数类型,Dart 必须得写参数类型,{}、;也必须写,要不然 Dart 就真的和 python 差不多了

2. Dart 支持 var 动态类型

Dart 静动态类型都支持,再加上高级语言特性,这样就可以像怎么写就怎么写了,即可以写成传统的java面向对象、处处皆对象的代码风格,也可以像kotlin一样,还可以像python一样,现在语言的差异越来越小了,Dartpython的差异很小了,说实话,我是比较喜欢python的,极简是有种魔力的,粘上就忘不了了

3. Dart 有性能优势

Dart可以在没有锁的情况下进行对象分配和垃圾回收。就像JavaScript一样,Dart避免了抢占式调度和共享内存(因而也不需要锁),所以Dart可以更轻松地创建以60fps运行的流畅动画和转场。这个在你使用Dart开发出App之后必定会深有感触


基本数据类型

Dart 基本数据类型:

  • 动态类型 - vardynamic
  • 数值型 - Numintdoublebool(布尔值)
  • 集合型 - ListMap,Dart 没有数组的概念,数组就等于集合
  • 文本型 - String
  • 方法类 - Function

下面仔细说下:

1. vardynamic是动态类型

2. 新的数学类型 Num

intdouble大家知道是什么,那这个Num是仅限于数字的动态类型,数值可以是int也可以是double

  num name = 10;

  void test() {
    name = 11;
    name = 11.2;
  }

3. Dart 没有 kotlin 这么变态的非 null 要求,声明的变量初始值可以给 null

var name ;

4. var 的特性

var 声明的变量,初始值要是 null 的话,后面给什么值都可以,但只要 var 的变量给初始值明确类型了,那么后面就只能是这个类型的数据了

  // 这样 OK
  var name ;
  void test() {
    name = 11;
    name = "AA";
  }
  
  // 这样报错
  var name = 10;
  void test() {
    name = 11;
    name = "AA";
  }

5. dynamic

dynamic 是不确定类型和var是一样的,但是var是给开发人员用的,dynamic是Dart 内部用的,我们也可以写dynamic,但是一般有dynamic的地方都自动隐藏了,dynamic这个关键字自动提示是没有的,就是说Dart不建议我们使用dynamic,我们知道dynamic什么意思就行了:dynamic修饰的变量,可以赋给任何类型的值


运算符

常用的就不说了,说些有变化的

1. /

在java中取整,5/3=1;但是在Dart中就不是取整了,而是带小数点了,5/3=1.6666...

2. ~/ -

在Dart中是取整的意思,5/3=1

3. ==

Dart 的==判断的就不是引用一样不一样了,而是判断的等号2边内容一样不一样

4. identical(name1, name2)

identical在Dart中才是判断应用一样不一样的

5. ??=

给null赋值,若这个参数==null,那么就=后面的这个数,当然大家使用??也是可以的,??两边可以接表达式的

var name;
print(name ??= 10);
~~~~~~~~log~~~~~~~~~~~
I/flutter: 10

6. =>

单行时可以省略{}

Function test1 = (var name, var age) => print(name + age);

7. ..

进行链式调用,非常简便

    var book = Book("AA", 12)
      ..name = "BB"
      ..age = 15;

8. ?.

null的话不报错

  var book = Book("AA", 12, "CC");
  book?.name = "BB";

9. isis!as

类型判断,转换类型,详细不展开了,大家都知道

  if (book1 is Book) {
    book1.name = "AA";
  }

  (book2 as Book).name = "DD";

switch

Dart 中的 switch case 支持基本数据类型和对象类型,另外还可以给每个 case 加上别名,用于指定跳转到某个 case 执行代码

    var name = "BB";
    switch (name) {
      as:
      case "AA":
        print("AA");
        break;
      case "BB":
        print("BB");
        continue as;
        break;
      case "CC":
        print("CC");
        break;
    }
    
~~~~~~~~~log~~~~~~~~~
I/flutter: BB
I/flutter: AA

比如上面我们给AA这个case加上as这个标记之后,在BB中我们就可以使用continue这个关键字跳到AA这个case去执行代码,不管AA符不符合判断,后会执行AA这个case 的代码


方法上的变化

1. Dart 中方法都是有返回值的,即便我们写void其实也是返回的null,这点大家知道一下就行

2. 参数花样

Dart 用{}表示可选参数,用[]表示位置参数,没 python 好使

  // 可选参数,用 xx:xx 传值
  void test1(var name1, {var name2 = 10, var name3 = 20}) {
    print("result = $name1,$name2,$name3");
  }
  
  // 位置参数,位置是固定的,你要是想给 name3赋值,必须先给name2赋值
  void test2(var name1, [var name2, var name3]) {
    print("result = $name1,$name2,$name3");
  }
  
  test1("AA", name2: 55);
  test2("BB",18,19);

3. 方法皆对象

Dart 秉承高级语言的特性,一切解释对象,方法本身也不例外,熟悉 koltin、python 的朋友一定不会谋生

  void man(){
    print("man");
  }
  
  var f = man;
  f();

比如上面,我们可以声明一个属性对象,用别的方法赋值给该对象,然后加()的方式运行该方法

4. 参数方法

我们来看下 Dart 中方法作为参数的使用

  // 声明方法
  void textView(void click(var name)) => click("AA");
  // 使用方法
  textView((var name) => print(name));

5. 匿名方法

其实在上面4中就展示了匿名方法,这里再强调一下,Dart 中匿名方法语法:返回值 (参数类型 参数名,xxx){},没有返回值的可以不写,实现单行可以用=>代替{}

举个例子:

void textView(String click(var name)) => click("AA");
  
textView((var name) {
  print(name);
  return "AA";
});

6. 闭包

Dart 的闭包和 JS、python 一个意思,是定义在方法里面的方法,其特性:

  • 闭包是一个对象
  • 闭包定义在其他方法内部
  • 闭包可以访问外部方法的布局变量,并持有其状态。这是闭包的最大用途,通过闭包的方式把一个方法内部的属性暴露出去,因为方法是可以返回方法的,Dart 中方法也是对象一样可以当做返回值处理

很多人说闭包学不会,看了很多资料还是不明白,其实吧这样跟大家说:大家把闭包看成对象就行了

比如下面这个例子,我们拿到闭包,操作外层方法的数据不停的自增,我们对调用几次闭包,大家会发现Z合格数据是不停增加的

// 闭包
sum(){
  var num = 0;
  sum2(){
    num++;
    print(num);
  }
  return sum2;
  
  // 也可以这么写,匿名的方式用的最多
  return (){
    num++;
    print(num);
  };
}

// 多调用闭包几次
void main(){
  Function a = sum();
  a();
  a();
  a();
  a();
  a();
  a();
}

~~~~~~~~~~log~~~~~~~~~~
1
2
3
4
5
6

结果是不会骗人的,大家就把闭包看成是一个包含外层数据的匿名实现类,当成对象看就好理解了,这是最经典的一个例子


面向对象上的变化

1. 可以省略 new

上文说过 Dart 创建对象可以省略new,很棒的设计,体验上像 python 极简主义靠拢

var book = Book("AA", 12);

2. Dart 默认自带get/set方法

3. Dart 中方法是不能重载的

4. Dart 没有public,private

Dart 的可见范围是以library库为单位的,每一个 Dart 文件就是一个库,Dart 中_表示库级别私有,_即可以修饰变量,也可以修饰对象,还可以修饰方法,这点又是和 python 一样

// 这样的对象,除了这个库文件,哪也别想用,变量我就举例了
class _Book {
  var name, age;

  _Book(this.name, this.age);

  speak(){

  }
}

5. 计算属性

Dart 属性默认自动生成get、set方法,但是大家也可以自己写,但是自己写的get、set就有区别了,看下面:

class RectTest {
  var width, height;

  RectTest(this.width, this.height);

  get area => width * height;

  set area(value) => width = value;
}

void main() {
  var rect = RectTest(20, 12);
  print(rect.area);
  rect.area = 30;
  print(rect.area);
  print(rect.width);
}

~~~~~~~~~~~~~log~~~~~~~~~~~~~~~
240
360
30
  • 要自己写get、set的话,该属性就不能声明,写了get、set方法的话就当是生命了一个变量,该变量set方法中不能给自己赋值(会陷入无限递归的状态),只能给别的属性赋值,大家看例子中的结果也能看出来,可以自己试下

6. 构造方法

Dart 中构造方法变化较大

  • 6.1 首先 Dart 像 java 一样提供一个默认的空的构造方法,但是一旦我们自己实现构造方法的话,这个默认的构造方法就会失效,我们自己的写的构造方法会替代默认的构造方法,另外 Dart 也提供了便利的语法糖在里面
class Book {
  var name, age;
    
  // 标准写法
  Book(var name, var age){
    this.name = name;
    this.age = age;
   }
  
  // 语法糖1
  Book(this.name, this.age){
   }
  
   // 语法糖2
   Book(this.name, this.age);
}

有一点要明确,这样的构造方法里,this的赋值是在构造方法方法体之前执行的

  • 6.2 Dart 蛋疼的不支持重载,所以 Dart 提供了命名构造方法,就是类名+方法名的方式实现多构造方法
class Book {
  var name, age;

  Book(this.name, this.age);
  Book.withName(this.name);
  Book.withAge(this.age);
}

然后自动提示就可以显示有多个构造方法了

  • 6.3 常量构造方法,若是有一个对象他的值都不需要变化的话我们就可以使用常量构造函数构造一个常量,这样的话对象的值在编译期就能知道,运行速度上有优势,这个需要结合 const 使用,具体场景估计也就是枚举了吧
// const 的对象要求属性都是不可变的,也就是 final 的
class Book {
  final name, age;

  const Book(this.name, this.age);
}

void main() {
  const book = const Book(12,112);
}
  • 6.4 工厂构造方法,在普通构造方法前加factory关键字,这个是配和私有构造方法使用的,看下面的例子
class Book {
  var name, age;

  factory Book(var name){
    return Book._withName(name);
  }

  // 私有构造方法
  Book._withName(this.name);

  Book._withAge(this.age);

}
  • 6.5 给 final 赋值,final 描述的一般都是不可变的值,Dart 允许我们声明 final 时给个null,但是在代码运行前必须初始化,这个地方就是构造方法,方式有2种:

方式1:在构造方法后面跟:给 final 赋值

class Book {
  var name, age;

  final title;

  Book(this.name, this.age, var title) : this.title = title {}

}

方式2:直接在构造方法中赋值,利用this.xxx在方法体之前执行的特性

class Book {
  var name, age;

  final title;

  Book(this.name, this.age, this.title);
}
  • 6.6 对象call方法,高级语言中允许把方法当做对象使用,Dart 中允许大家把对象当方法使用book1(),本质是调用book1里面的指定方法call
class Book {
  var name, age;

  final title;

  Book(this.name, this.age, this.title);

  call( var value ){
    print("$name同学请$value同学上台演讲");
  }
}

void main() {
  var book1 = Book("AA", 12, "CC");
  var book2 = Book("AA", 12, "CC");

  book1("PP");
}

~~~~~~~~~~~~~~~log~~~~~~~~~~~~~~~~~~
AA同学请PP同学上台演讲

其实什么++,--之类的都是运用的这个思路,不过不推荐这个搞,这样会模糊对象和方法的边界,那代码就不好阅读理解了

  • 6.7 重载自己的构造函数

首先 Dart 里是不允许重载的,但有时候我们的构造函数根据情况有很多,会有一个统一的基础构造函数,其他的构造函数根据情况不同来使用这个基本的构造函数

这个例子大家看构造函数的写法就行了,其他的没用

class FreeSlideTransition extends AnimatedWidget {

  Animation<Offset> animation;
  var child;
  Offset begin;
  Offset end;
  FreeSlideTransitionMode type;

  // 构造方法的多态,写着有点麻烦,看起来也不省事
  FreeSlideTransition(this.type, this.child,
      {Key key, Animation<double> animation, Offset begin, Offset end})
      : super(key: key, listenable: animation) {
    this.animation = Tween<Offset>(begin: begin, end: end).animate(animation);
  }

  FreeSlideTransition.reverseX(
      {Widget child,
      Animation<double> animation,
      Key key,
      Offset begin,
      Offset end})
      : this(FreeSlideTransitionMode.reverseX, child,
            key: key, animation: animation, begin: begin, end: end);

  FreeSlideTransition.reverseY(
      {Widget child,
      Animation<double> animation,
      Key key,
      Offset begin,
      Offset end})
      : this(FreeSlideTransitionMode.reverseY, child,
            key: key, animation: animation, begin: begin, end: end);
}

7 继承

Dart 是单继承关系,子类不能继承父类的私有(属性、方法)和构造函数

Dart 最蛋疼的是就是继承关系中的构造函数了,Dart 的子类默认使用父类的默认构造函数,若是父类没有默认的构造函数了,而是用户自定义的,那么子类必须显示的继承父类的一个构造函数,看下面的例子:

class Animal {
  var name, sex;

  Animal(this.name);

  Animal.withSex(this.sex);
}

class Dog extends Animal {
  Dog(name) : super(name);

  Dog.withSex(sex) : super.withSex(sex);
}

情况再复杂一点的是加上 final 赋值,中间用相联

class Dog extends Animal {
  final price;

  Dog.withSex(var sex, var price)
      : this.price = price,
        super.withSex(sex);
}

8. 多继承

Dart 中多继承专门有个词:Mixins,Dart 允许我们使用with关键字实现多继承,但是多继承本身非常危险,很容易出现各种问题的

标准写法:

class Animal {
  var age, sex;
}

class Cat {
  var name;

  speak() {
    print("CAT");
  }
}

class Dog {
  var name;

  speak() {
    print("DOG");
  }
}

class Bear {
  var name;

  speak() {
    print("BEAR");
  }
}

class MyPet extends Animal with Dog, Cat, Bear {
  var n;

  MyPet(this.n);
}

然后我们调用下 pet.speak() 方法看看

  var pet = MyPet();
  pet.speak();
  
  ~~~~~~~~log~~~~~~~~
  BEAR

这说明对于多继承来说,多个父类同名的属性和方法是以最后一个继承的父类的数据为准

并且多继承对父类要求很严格,要求父类不能有自己的构造方法,默认的除外...蛋疼不,并且多继承很容易出问题的,使用时要格外注意

多继承进一步就是组合了,用于模块间和架构内的功能组合,看下面的代码,这块我也没有什么体验,也是道听途说

class MyPet1 = Animal with Dog;
class MyPet2 = Animal with Cat;
class MyPet3 = Animal with Bear;

我有3种不同功能的宠物,注意这样写的话要求 MyPet1 这样的子类不能有自己的属性和方法,纯粹是为了功能组合而存在,大家要清楚

9. 抽象类

Dart 的抽象类中的抽象方法不用写abstract关键字,一般认为 Dart 的抽象类更像是接口,一般都是当接口用的

abstract class Cat{
  void speak();
}

10. 接口

Dart 的接口实在是怪,Dart 中其实是没有接口这个概念的,在 Dart 里接口就是对象,我们用implements关键字可以直接继承一个对象,但是该对象中的所有属性和方法都需要我们重写

class Animal {
  var name, sex;

  Animal(this.name);

  Animal.withSex(this.sex);
}

class Dog implements Animal {
  @override
  var name;

  @override
  var sex;
}

所以这里就体现出上面说的抽象类的重要性了,Dart 里我们一般把接口写成抽象类

abstract class Cat{
  void speak();
}

class Dog implements Cat {
  @override
  void speak() {
    // TODO: implement speak
  }
}

11. Mixin 混入

Dart 的 implements 限制不小,比如你继承一个 dart 中的 接口,你必须重写这个接口里面所有的属性和方法,不管这个方法是不是抽象的

abstract class A {
  runA();

  speakA() {}
}

abstract class B {
  runB();
}

class AA implements A, B {
  @override
  runA() {
    // TODO: implement runA
    return null;
  }

  @override
  runB() {
    // TODO: implement runB
    return null;
  }

  @override
  speakA() {
    // TODO: implement speakA
    return null;
  }
}

这样明显限制太大,很多时候用着并不舒服,所以 Dart 提供一种新的接口类型:Mixin,你实现 Mixin 类型的接口后,这样你就可以像 java 那样去实现接口了,注意实现接口时要用:with

mixin A {
  runA();

  speakA() {}
}

mixin B {
  runB();
}

class AA with A, B {
  @override
  runA() {
    // TODO: implement runA
    return null;
  }

  @override
  runB() {
    // TODO: implement runB
    return null;
  }
}

12. 重写操作符

这是个骚操作,会让我们的代码看着非常高大上,什么是操作符:+,-,++,>这些就是,我们在class内部使用operator关键字+操作符号就可以给我们的对象添加诸如+,-,++,>这样的操作了

class Book{
  var price;
  var _name = "AA";

  Book(this.price);

  operator >( Book otherBook ){
    return this.price > otherBook.price;
  }

  operator [](String attribute){
    switch(attribute){
      case "price":{return price;}break;
      case "name":{return _name;}break;
      default: {return null;}
    }
  }
}

void main() {

  var book1 = Book(20);
  var book2 = Book(30);

  print( book1 > book2 );
  print( book1["price"] );
  print( book1["name"] );
}

book1["price"]这可以让我们换个方式调用对象的属性,装逼用的,大家看上面的写法就成,用这个方法可以在外面拿到对象的私有属性


泛型

Dart 中的泛型和 JAVA 语法差不多

1. 类中使用泛型

class Location {
  Object x;
  Object y;

  Location(this.x, this.y);
}

2. 方法中使用泛型

class Location<T> {
  T x;
  T y;

  Location(this.x, this.y);
}

3. 集合中使用泛型

  • 3.1 list
// 不使用泛型限制数据类型
var names = ['aa', 'bb', 'cc', 111];

// 使用泛型之后
var names = <String>['aa', 'bb', 'cc'];
  • 3.2 map
// 不使用泛型限制数据类型
var infos = {1: 'one', 'name': 'why', 'age': 18}; 

// 使用泛型之后
Map<String, String> infos = {'name': 'why', 'age': '18'};

库的导入

前面简单的说了下导库,这里咱们详细来说说

1. Dart 导库的3种方式:

  • Dart 标准库 - 这里库都是 Dart 内部自带的,比如:dart:io、dart:html、dart:math
import 'dart:io';
  • Pub 包管理器 - 使用前缀:package:,像 Flutter 提供的包就是用 Pub 管理器导入
import 'package:flutter/material.dart';
  • 指定路径 - 可以是相对路径或绝对路径
import 'lib/student/student.dart';

2. show、hide、as 关键字

  • show - 只导入指定的文件
  • hide - 隐藏指定文件,其他都导入
  • as - 起别名
import 'lib/student/student.dart' show Student, Person;
import 'lib/student/student.dart' hide Person;
import 'lib/student/student.dart' as Stu;

// 使用的使用要加上别名
Stu.Student s = new Stu.Student();

这点其实和 python 是一模一样的

3. library、part 定义库

我们可以用 library 给库起个名字,没名字的库你也没法用不是,然后当库很大时,一个文件装不下时 part 就起作用了, 使用 part 可以把子文件关联进库主文件中,库打包的时候一起都打进去,不会造成文件缺失

使用思路:

  • 子文件使用 part of "库名" 的方式关联库主文件
  • 库主文件使用 子文件名.dart 的方式把子文件绑定进库里

主文件 AB.dart

library AB
part "mathUtils.dart";
part "dateUtils.dart";

子文件 mathUtils.dart

part of "AB.dart";

int sum(int num1, int num2) {
  return num1 + num2;
}

恩,有些麻烦,需要子文件和主文件都相互声明,有点绕,初上手会很困惑的,好在一切不合理的都会被消灭,这东西现在过时啦

4. export 定义库

export 就是用来代替 path 的,在 export 的时代,我们只需要在库主文件声明一下需要的子文件就行啦,不用再折腾子文件了

主文件 AB.dart

library AB;

export "mathUtils.dart";
export "dateUtils.dart";

子文件 mathUtils.dart

int sum(int num1, int num2) {
  return num1 + num2;
}

5. 延迟加载库

库的延迟加载比较奇葩,我是头一次遇见这样设计的,场景主要有以下几点:

  • 减少APP的初始启动时间
  • 执行A/B测试,例如尝试各种算法的不同实现
  • 加载很少使用的功能

要延迟加载一个库,需要先使用 eferred as 来导入:

import 'package:deferred/hello.dart' deferred as hello;

复制代码当需要使用的时候,调用loadLibrary() 函数来加载库:

greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}