# Dart教程 - 10 库的使用

前面在学习Dart的时候,基本所有的代码都是写在一个dart文件中,最多也只是简单的使用了import关键字,引入了其他的dart文件。在实际的开发中,代码量是很大的,所以会编写很多的dart文件,通过使用库管理,我们可以更好将相关的功能或类组织在一起,以便更好地维护和复用代码。同时我们可以引入一些内置的或第三方编写的库文件,提高开发效率,避免重复造轮子。

Dart中的库主要有三种:

  • 系统内置的库

  • 自定义的库

  • Pub包管理系统中的库

# 10.1 系统内置库

Dart 自带了一些常用的内置库,引入内置库的方式:

import 'dart:库名';
1

举个栗子:

比如我们进行数学运算,进行开根号运算:

import 'dart:math';

void main() {
  double result = sqrt(4); // 开根号运算
  print(result);

  int maxNum = max(3, 5); // 求较大的数
  print(maxNum);
}
1
2
3
4
5
6
7
8
9

上面我们使用 import 'dart:math'; 引入了 math 内置库,并使用了内置库中的开根号运算函数sqrt和求较大值的函数max

其实dart默认是导入了 dart:core 库的, dart:core 是 Dart 的核心库,包含了 Dart 的基本数据类型、集合类型、函数和异常处理等基本功能,在编码的时候无需显式导入即可使用。

举个栗子:

void main() {
  // 使用 dart:core 中的 print 函数
  print('Hello, Dart!');

  // 使用 dart:core 中的 List 类型
  var myList = [1, 2, 3];
  print(myList); // 输出:[1, 2, 3]
}
1
2
3
4
5
6
7
8

上面使用了print函数、列表,这些都是 dart:core 库中的,该库默认是导入的,不需要手动导入。

# 10.2 自定义的库

前面也已经使用了自定义库的导入,引入自定义库的方式:

import '目录名/文件名.dart'
1

举个栗子:

定义了一个Person.dart

class Person {
  String name;
  int age;

  Person(this.name, this.age);
}

1
2
3
4
5
6
7

定义了一个StrUtils.dart

class StrUtils {
  // 判断字符串是否为空
  static bool isEmpty(String? str) {
    return str == null || str.trim().isEmpty;
  }

  // 判断字符串是否不为空
  static bool isNotEmpty(String? str) {
    return !isEmpty(str);
  }

  // 去除字符串首尾空格
  static String trim(String? str) {
    return str?.trim() ?? '';
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

然后在main.dart中引入上面的两个dart文件。

Main.dart

import 'domain/Person.dart';
import 'util/StrUtils.dart';
import 'Test.dart';

void main() {
  Person person = Person("逗比", 12);
  print(StrUtils.isEmpty(person.name));

  Test test = new Test();
}
1
2
3
4
5
6
7
8
9
10

如果要引入的dart文件在当前目录,直接写文件名 Test.dart 即可。

# 10.3 Pub包管理系统中的库

pub 包管理系统是官方的包管理工具,用于查找、安装和发布 Dart 包。这个系统允许开发者将自己编写的代码封装成包,供其他开发者在自己的项目中使用,也可以方便地使用其他开发者分享的包来扩展自己的项目功能。

一般情况下,我们都是在自己的项目中集成其他人开发的包,来提高我们的开发效率。

我们可以通过如下地址查找库:

https://pub.dev/packageshttps://pub-web.flutter-io.cn/packages
1
2
3

使用Pub包管理系统,需要一下几个步骤:

  1. 首先可以在上面的网页中查找自己需要的库;
  2. 需要在自己的项目根目录创建一个 pubspec.yaml 文件;在 pubspec.yaml 文件中,配置依赖的库的信息,包括名称、版本、描述等;
  3. 然后在根目录下运行 dart pub get 命令,将库下载到本地;
  4. 然后就可以在代码中引入库中的功能了。

举个栗子:

我们想发起http请求,需要使用Pub包管理系统中http库。

# 1 查找库

我们可以在上面地址的网页中查找到http库

在库的详情页,我们可以看到库的安装方式:

我们使用 pubspec.yaml 文件安装即可。

# 2 新建 pubspec.yaml 文件

在项目根目录下新建 pubspec.yaml 文件,内容如下:

name: hello_dart # 项目名称
description: My Dart application # 项目描述
version: 1.0.0  # 项目版本

environment:  # 指定sdk版本约束
  sdk: '>=2.12.0 <3.0.0'

dependencies:
  http: ^0.13.6


dev_dependencies:
  # 添加开发时需要的依赖包,如果有的话
1
2
3
4
5
6
7
8
9
10
11
12
13

有的依赖对SDK版本有要求,例如当dart版本是3.0以下是,引入http1.0.0就会有如下错误:

Because hello_dart depends on http >=1.0.0 which requires SDK version >=3.0.0 <4.0.0, version solving failed.
1

# 3 下载依赖

在上面保存 pubspec.yaml 文件的时候,VSCode就会自动下载依赖。

我们也可以在根目录下运行 dart pub get 命令来下载依赖;

# 4 引入和使用依赖

下载依赖后,就可以引入依赖并使用了,举个栗子:

import 'dart:convert' as convert;
import 'package:http/http.dart';

void main(List<String> arguments) async {
  var url = Uri.http('www.doubibiji.com', '/apis/category/allNoteList', {});

  var response = await get(url);
  if (response.statusCode == 200) {
    var jsonResponse =
        convert.jsonDecode(response.body) as Map<String, dynamic>;
    print('http result: $jsonResponse');
  } else {
    print('Request failed with status: ${response.statusCode}.');
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上面的代码中使用 import 'package:http/http.dart'; 引入了http。

其中的函数 get(url) 就是http提供的,用于发起 get 请求。

关于 await 的使用,后面讲异步的时候再讲解,这里知道它在等待请求的信息即可。

# 10.4 库名冲突

如果我们引入的多个库存在相同名称的内容的时候,我们可以使用 as 关键字来避免冲突。

举个栗子:

我们在两个包下都有Person.dart,然后如何在Main.dart同时引入两个Person类呢?

Main.dart

import 'domain/Person.dart' as Per1;
import 'pojo/Person.dart' as Per2;

void main(List<String> args) {
  Per1.Person p1 = Per1.Person("Doubi", 12);
  Per2.Person p2 = Per2.Person("Niubi", 13);
}
1
2
3
4
5
6
7

我们可以在引入的时候使用 as 起别名,然后在使用的时候,在前面添加别名。

在上面我们使用http请求的时候,一般也是会起个别名,防止冲突:

// 引入的时候使用别名,防止冲突
import 'package:http/http.dart' as http;
// 然后使用http.get()
var response = await http.get(url);
1
2
3
4

# 10.5 部分导入

如果希望只导入库中某些内容,我们可以使用 showhide 关键字。

  • show关键字: 只导入需要的部分
  • **hide关键字:**隐藏不需要的部分

举个栗子:

在http库中,提供了 getpost 方法,如下:

import 'package:http/http.dart' as http;

void main(List<String> arguments) async {
  var url = Uri.http('www.doubibiji.com', '/apis/category/allNoteList', {});

  var response1 = await http.get(url);
  var response2 = await http.post(url);
}
1
2
3
4
5
6
7
8

我们可以只导入 get 函数:

import 'package:http/http.dart' as http show get;
1

这样 http.post(url); 将会报错。

也可以隐藏 get 函数:

import 'package:http/http.dart' as http hide get;
1

这样将不会导入 get 函数,http.get(url); 将会报错。

# 10.6 库的定义

在开发中,如果一个库文件太大,将所有内容保存到一个文件中是不太合理的,我们有可能希望将这个库进行拆分,每个文件都包含库中的一部分代码,这样可以更好地组织和管理大型项目中的代码。

在之前我们可以使用part关键字,但是现在不推荐了,替代方案是使用export。

举个栗子:

我们现在有一个库,utils.dart

// utils.dart

int add(int a, int b) {
  return a + b;
}

class Point {
  int x;
  int y;

  Point(this.x, this.y);
}
1
2
3
4
5
6
7
8
9
10
11
12

现在我们想将上面的库拆分成多个文件,将 add() 函数和 Point 定义到不同的dart文件中。

于是创建了 math_utils.dart,将 add() 函数定义到其中:

// math_utils.dart

int add(int a, int b) {
  return a + b;
}
1
2
3
4
5

继续,创建了 geometry_utils.dart,将 Point 定义到其中:

// geometry_utils.dart

class Point {
  int x;
  int y;

  Point(this.x, this.y);
}
1
2
3
4
5
6
7
8

现在已经将 utils.dart 库中的内容分到两个文件中了,现在需要使用 export 关键字将这两个文件中的公共部分暴露给其他库,编辑 utils.dart 为:

// utils.dart

library my_utils;

export 'math_utils.dart';
export 'geometry_utils.dart';
1
2
3
4
5
6

我们现在在 utils.dart 中,将 math_utils.dartgeometry_utils.dart 导出,然后使用 library 关键字定义库的名称。

library 关键字的作用主要是为了将多个相关的 .dart 文件组织为一个库。在大多数情况下,特别是在简单的项目中或者所有相关文件都在同一个文件夹下时,library 关键字是可选的,不写也不会产生影响。所以上面 library my_utils; 这句代码,不写也没有影响。

现在编写 Main.dart,在 Main.dart 中引入和使用 utils.dart

// main.dart
import 'lib/utils.dart';

void main() {
  int result = add(3, 5);
  print('The sum is: $result');

  Point point = Point(10, 20);
  print('Point: (${point.x}, ${point.y})');
}
1
2
3
4
5
6
7
8
9
10

通过 libraryexport 可以将库拆分成多个文件,每个文件包含库中的一部分代码,以实现更好的代码组织和管理。

上面的代码结构如下: