Dart 基础教程
Dart 是由 Google 开发的一种开源、通用的编程语言,主要用于构建跨平台的应用程序,尤其是 Flutter 应用。Dart 具有面向对象的特性,支持类、接口、混入等高级特性,并且提供了强大的异步编程支持。本文将带你了解 Dart 的基础知识,帮助你快速上手。
目录
1. Dart 简介
Dart 是一种面向对象的、类基的编程语言,支持垃圾回收,具有强大的异步编程能力。Dart 的设计目标是提供高性能、可扩展且易于学习的语言,适用于客户端和服务器端开发。它被广泛应用于 Flutter 应用开发中,但也可以用于构建 Web 应用、命令行工具等。
主要特点:
- 面向对象:支持类、继承、混入等特性。
- 静态与动态类型:支持可选的类型注解。
- 异步支持:内置支持异步编程,通过
Future和Stream。 - 高性能:通过 AOT 编译和 JIT 编译提供高性能执行。
- 丰富的标准库:提供了丰富的核心库,涵盖集合、异步、I/O 等功能。
2. 开发环境搭建
要开始学习 Dart,可以选择以下几种开发环境:
2.1 安装 Dart SDK
-
下载 Dart SDK:
前往 Dart 官方网站 下载适用于你的操作系统的 Dart SDK。
-
安装 Dart SDK:
根据操作系统的不同,按照官网提供的安装指南进行安装。
-
配置环境变量:
将 Dart 的
bin目录添加到系统的环境变量中,以便在命令行中使用dart命令。示例(macOS/Linux):
export PATH="$PATH:/path/to/dart-sdk/bin"示例(Windows):
将
dart-sdk\bin路径添加到系统环境变量的 PATH 中。 -
验证安装:
打开终端或命令提示符,运行以下命令检查 Dart 是否安装成功:
dart --version
2.2 使用 IDE
Dart 可以在多种集成开发环境(IDE)中编写和运行,推荐使用以下几种:
-
Visual Studio Code:
- 安装 VS Code 后,通过扩展市场安装 Dart 和 Flutter 插件,提供语法高亮、自动补全、调试等功能。
-
IntelliJ IDEA / Android Studio:
- 安装后,通过插件管理器安装 Dart 插件,支持丰富的开发功能。
-
其他编辑器:
- 如 Sublime Text、Atom 等也有 Dart 支持的插件,但功能可能不如 VS Code 和 IntelliJ IDEA 丰富。
2.3 使用 DartPad
DartPad 是一个在线的 Dart 编辑器,适合快速尝试和学习 Dart 代码,无需本地安装。
3. 基本语法
3.1 变量与数据类型
Dart 是一种可选类型语言,支持静态类型和动态类型。你可以使用 var、final、const 来声明变量。
void main() {
// 静态类型
int age = 30;
double height = 5.9;
String name = 'Alice';
bool isStudent = false;
// 动态类型
var city = 'New York'; // 类型推断为 String
dynamic anything = 100; // 可以改变类型
anything = 'Now I am a string';
}
var:根据初始化值推断类型,类型一旦确定不能改变。final:声明一个只能赋值一次的变量,运行时常量。const:声明编译时常量,必须在编译时就确定值。
void main() {
final String language = 'Dart';
const double pi = 3.14159;
}
3.2 运算符
Dart 支持多种运算符,包括算术运算符、关系运算符、逻辑运算符、赋值运算符等。
void main() {
int a = 10;
int b = 3;
// 算术运算符
print(a + b); // 13
print(a - b); // 7
print(a * b); // 30
print(a / b); // 3.3333333333333335
print(a ~/ b); // 3(整除)
print(a % b); // 1
// 关系运算符
print(a > b); // true
print(a < b); // false
print(a == b); // false
print(a != b); // true
// 逻辑运算符
bool isAdult = a > 18;
bool isEmployed = true;
print(isAdult && isEmployed); // true
print(isAdult || isEmployed); // true
print(!isEmployed); // false
// 赋值运算符
a += 5; // a = a + 5
print(a); // 15
}
3.3 控制流
条件语句
void main() {
int score = 85;
if (score >= 90) {
print('A');
} else if (score >= 80) {
print('B');
} else if (score >= 70) {
print('C');
} else {
print('F');
}
}
switch 语句
void main() {
String command = 'OPEN';
switch (command) {
case 'CLOSED':
print('The door is closed.');
break;
case 'OPEN':
print('The door is open.');
break;
default:
print('Unknown command.');
}
}
循环
for 循环
void main() {
for (int i = 0; i < 5; i++) {
print('Iteration $i');
}
}
while 循环
void main() {
int i = 0;
while (i < 5) {
print('Iteration $i');
i++;
}
}
do-while 循环
void main() {
int i = 0;
do {
print('Iteration $i');
i++;
} while (i < 5);
}
for-in 循环
void main() {
List<String> fruits = ['Apple', 'Banana', 'Cherry'];
for (var fruit in fruits) {
print(fruit);
}
}
4. 函数
4.1 声明与调用
函数是 Dart 中的基本构建块,用于封装可重用的代码。
void main() {
sayHello('Alice');
int sum = add(3, 4);
print('Sum: $sum');
}
void sayHello(String name) {
print('Hello, $name!');
}
int add(int a, int b) {
return a + b;
}
4.2 箭头函数
简化的函数语法,适用于单表达式函数。
int add(int a, int b) => a + b;
void main() {
print(add(5, 7)); // 12
}
4.3 匿名函数
没有名称的函数,通常用于回调或内联函数。
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
numbers.forEach((number) {
print(number);
});
// 使用箭头函数
numbers.forEach((number) => print(number));
}
5. 面向对象编程
5.1 类与对象
Dart 是一种面向对象的语言,支持类和对象的概念。
class Person {
String name;
int age;
// 构造函数
Person(this.name, this.age);
// 方法
void introduce() {
print('Hi, my name is $name and I am $age years old.');
}
}
void main() {
Person alice = Person('Alice', 30);
alice.introduce(); // Hi, my name is Alice and I am 30 years old.
}
5.2 继承
Dart 支持类的继承,可以通过 extends 关键字实现。
class Animal {
void eat() {
print('Animal is eating.');
}
}
class Dog extends Animal {
void bark() {
print('Dog is barking.');
}
}
void main() {
Dog myDog = Dog();
myDog.eat(); // Animal is eating.
myDog.bark(); // Dog is barking.
}
5.3 抽象类与接口
抽象类
抽象类不能被实例化,用于定义子类必须实现的方法。
abstract class Shape {
double area();
}
class Circle extends Shape {
double radius;
Circle(this.radius);
@override
double area() => 3.14159 * radius * radius;
}
void main() {
Circle circle = Circle(5);
print('Area: ${circle.area()}'); // Area: 78.53975
}
接口
Dart 中的每个类都隐式地定义了一个接口。可以通过 implements 关键字实现接口。
class Animal {
void eat() {
print('Animal is eating.');
}
}
class Bird implements Animal {
@override
void eat() {
print('Bird is eating.');
}
void fly() {
print('Bird is flying.');
}
}
void main() {
Bird sparrow = Bird();
sparrow.eat(); // Bird is eating.
sparrow.fly(); // Bird is flying.
}
6. 集合类型
6.1 List
Dart 中的 List 是有序的可变集合,可以存储多个元素。
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
print(numbers); // [1, 2, 3, 4, 5]
// 添加元素
numbers.add(6);
print(numbers); // [1, 2, 3, 4, 5, 6]
// 访问元素
print(numbers[0]); // 1
// 遍历
for (var number in numbers) {
print(number);
}
}
6.2 Set
Set 是无序且唯一的集合,不能包含重复的元素。
void main() {
Set<String> fruits = {'Apple', 'Banana', 'Cherry'};
print(fruits); // {Apple, Banana, Cherry}
// 添加元素
fruits.add('Date');
print(fruits); // {Apple, Banana, Cherry, Date}
// 尝试添加重复元素
fruits.add('Apple');
print(fruits); // {Apple, Banana, Cherry, Date}
// 遍历
for (var fruit in fruits) {
print(fruit);
}
}
6.3 Map
Map 是键值对的集合,每个键都是唯一的。
void main() {
Map<String, int> ages = {
'Alice': 30,
'Bob': 25,
'Charlie': 35,
};
print(ages); // {Alice: 30, Bob: 25, Charlie: 35}
// 添加或更新元素
ages['David'] = 40;
print(ages); // {Alice: 30, Bob: 25, Charlie: 35, David: 40}
// 访问元素
print(ages['Alice']); // 30
// 遍历
ages.forEach((key, value) {
print('$key is $value years old.');
});
}
7. 异步编程
Dart 提供了强大的异步编程支持,主要通过 Future 和 Stream 实现。
7.1 Future
Future 表示一个可能在将来某个时刻完成并返回结果的操作。
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return 'Data fetched';
}
void main() async {
print('Fetching data...');
String data = await fetchData();
print(data); // Data fetched
}
7.2 async & await
async 和 await 关键字用于编写异步代码,使其看起来更像同步代码。
Future<void> printData() async {
String data = await fetchData();
print(data);
}
void main() async {
await printData();
}
7.3 Stream
Stream 是一个异步数据序列,可以逐个地处理事件。
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
void main() async {
await for (var value in countStream(5)) {
print(value); // 1, 2, 3, 4, 5 每秒打印一个
}
}
8. 错误与异常处理
Dart 提供了异常处理机制,通过 try-catch 块捕获和处理异常。
void main() {
try {
int result = divide(10, 0);
print(result);
} catch (e) {
print('Error: $e');
} finally {
print('This is always executed.');
}
}
int divide(int a, int b) {
if (b == 0) {
throw Exception('Division by zero');
}
return a ~/ b;
}
try:包裹可能抛出异常的代码。catch:捕获并处理异常。finally:无论是否发生异常,都会执行的代码块。
自定义异常
可以定义自定义异常类,以便更好地处理特定的错误情况。
class NegativeNumberException implements Exception {
String cause;
NegativeNumberException(this.cause);
}
int sqrt(int x) {
if (x < 0) {
throw NegativeNumberException('Cannot calculate square root of negative number');
}
return x; // 这里只是示例,实际应该计算平方根
}
void main() {
try {
sqrt(-4);
} catch (e) {
if (e is NegativeNumberException) {
print('Custom Exception: ${e.cause}');
} else {
print('Unknown Exception: $e');
}
}
}
9. Dart 工具与包管理
9.1 Pub
pub 是 Dart 的包管理工具,用于管理项目的依赖、发布包等。常用命令包括:
-
添加依赖:
在
pubspec.yaml中添加依赖,然后运行:dart pub get -
升级依赖:
dart pub upgrade -
发布包:
参考 pub.dev 发布指南
9.2 常用包
- http:用于发送 HTTP 请求。
- json_serializable:自动生成 JSON 解析代码。
- provider:状态管理解决方案。
- sqflite:SQLite 数据库支持。
- path:文件路径处理。
示例:使用 http 包发送请求
import 'package:http/http.dart' as http;
Future<void> fetchData() async {
var url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
var response = await http.get(url);
if (response.statusCode == 200) {
print('Response data: ${response.body}');
} else {
print('Request failed with status: ${response.statusCode}.');
}
}
10. 示例项目
通过一个简单的示例项目,综合运用所学知识。
示例项目:待办事项应用
-
创建项目:
dart create todo_app cd todo_app -
编辑
pubspec.yaml:添加依赖:
dependencies: http: ^0.13.4 provider: ^6.0.0 -
实现核心功能:
-
定义模型:
class Todo { final int id; final String title; bool completed; Todo({ required this.id, required this.title, this.completed = false, }); } -
创建 Provider:
import 'package:flutter/foundation.dart'; import 'todo.dart'; class TodoProvider with ChangeNotifier { List<Todo> _todos = []; List<Todo> get todos => _todos; void addTodo(Todo todo) { _todos.add(todo); notifyListeners(); } void toggleTodoStatus(int id) { var todo = _todos.firstWhere((todo) => todo.id == id); todo.completed = !todo.completed; notifyListeners(); } } -
构建 UI:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'todo_provider.dart'; import 'todo.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => TodoProvider(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Todo App', home: TodoPage(), ); } } class TodoPage extends StatelessWidget { final TextEditingController _controller = TextEditingController(); @override Widget build(BuildContext context) { var todoProvider = Provider.of<TodoProvider>(context); return Scaffold( appBar: AppBar(title: Text('Todo List')), body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( child: TextField( controller: _controller, decoration: InputDecoration(labelText: 'Enter todo'), ), ), IconButton( icon: Icon(Icons.add), onPressed: () { if (_controller.text.isNotEmpty) { todoProvider.addTodo(Todo( id: DateTime.now().millisecondsSinceEpoch, title: _controller.text, )); _controller.clear(); } }, ) ], ), ), Expanded( child: ListView.builder( itemCount: todoProvider.todos.length, itemBuilder: (context, index) { var todo = todoProvider.todos[index]; return ListTile( title: Text(todo.title), trailing: Checkbox( value: todo.completed, onChanged: (value) { todoProvider.toggleTodoStatus(todo.id); }, ), ); }, ), ) ], ), ); } }
-
-
运行项目:
dart run
11. 学习参考资源
-
官方文档:
-
在线教程:
-
社区与支持: