位置:首页 > Dart > Dart 基础教程:从环境搭建到异步编程的入门梳理

Dart 基础教程:从环境搭建到异步编程的入门梳理

时间:2026-08-25  |  作者:骑光打字机  |  阅读:0

目录

  1. 环境搭建与第一个 Dart 程序
  2. 变量、数据类型与常用运算
  3. 控制流程与函数写法
  4. 面向对象、集合与异常处理
  5. 异步编程、综合案例与最佳实践

前言

Dart 常和 Flutter 一起出现,但很多初学者真正卡住的,往往是语言基础本身:变量怎么声明、空安全怎么用、函数和类如何组织、异步代码该从哪里读起。本文按“先跑通环境,再理解语法,最后拼成完整示例”的顺序重写,保留原始命令、代码和关键数值,帮助你快速建立一套可直接上手的 Dart 基础框架。

Dart 常被拿来和 Flutter 一起学习,但很多初学者卡住的并不是框架,而是语言本身:变量怎么声明、空安全怎么处理、函数和类该怎么写、异步代码到底怎么读。下面这篇入门整理按“环境搭建 → 基础语法 → 常用能力 → 综合练习”的顺序展开,保留原始示例代码和关键命令,帮助你先把 Dart 跑起来,再对常见写法建立一套清晰判断。

环境搭建与第一个 Dart 程序

如何安装 Dart SDK

开始之前,先把 Dart 开发环境装好。原始安装入口仍然是官方页面:

Dart 基础语法信息图,展示变量声明、常用类型、类型转换和空安全运算的核心关系。
Dart 基础语法速览用一张结构图梳理 Dart 初学者最容易混淆的变量、类型与空安全语法。

能正确输出版本信息,就说明命令行环境已经可用,后续示例可以直接运行。

第一个程序怎么写

Dart 程序的入口是 main()。先从最简单的输出开始:

void main() {
  print('Hello, Dart World!');
}

运行结果:

Hello, Dart World!

如果这段代码可以正常输出,说明你的 SDK、命令行和基础执行链路都没有问题,后面就可以进入语法学习。

变量、数据类型与常用运算

变量声明有哪些常见方式

Dart 支持类型推断、显式声明、动态类型以及常量声明。刚入门时,先分清 var、显式类型、dynamic、final 和 const 的使用场景,比死记语法更重要。

Dart 面向对象与异步编程信息图,展示类结构、继承与 Mixin、Future 和 Stream 的用法差异。
从对象模型到异步流程这张图把 Dart 从类设计到异步模型的关键概念放在同一视图中,便于建立整体认识。
var name = 'Alice';      // 类型推断
String city = 'London';  // 显式声明
dynamic anything = 5;    // 动态类型
final PI = 3.14;         // 运行时常量
const gra vity = 9.8;     // 编译时常量

这里可以直接记住两点:一是一般变量优先用明确或可推断的类型;二是不需要修改的值优先考虑 final,如果值在编译期就能确定,再使用 const。

Dart 的基本数据类型够不够用

对多数入门练习来说,Dart 的整数、浮点数、布尔值、字符串、列表和映射已经覆盖了主要需求:

int age = 25;                  // 整数
double price = 9.99;           // 浮点数
bool isStudent = true;         // 布尔值
String greeting = 'Hello';     // 字符串
List numbers = [1,2,3];   // 列表
Map scores = {    // Map集合
  'Math': 90,
  'English': 85
};

其中 List 和 Map 也顺带体现了 Dart 的泛型写法,这对后面理解集合和自定义类会有帮助。

类型检查与转换怎么处理

开发中经常会碰到“字符串转数字”“数字再转回字符串”的情况。Dart 对此提供了直接可读的写法:

var value = '123';
print(value is String);  // true
int numValue = int.parse(value);
String strValue = numValue.toString();

is 用于类型判断,int.parse() 和 toString() 则是最常见的双向转换方式。入门阶段把这三种写法用熟,已经能解决不少基础数据处理问题。

基础运算符和空安全运算符怎么理解

Dart 的算术运算与常见语言差别不大,但空安全相关运算符是必须尽早掌握的部分。

int a = 10, b = 3;
print(a + b);   // 13
print(a ~/ b);  // 3 (整除)
print(a++);     // 10 (后置递增)
String nullableName;
print(nullableName  'Default');  // 空合并
print(nullableName.length);       // 安全访问

~/ 表示整除,适合需要整数结果的场景。空安全部分里, 用来提供默认值,. 用来避免空对象访问报错,这两者在实际项目里的出场率非常高。

控制流程与函数写法

条件判断与三元表达式

当你需要根据不同条件输出不同结果时,Dart 的 if / else if / else 结构足够直接;条件简单时,也可以改用三元表达式压缩代码。

int score = 85;
if (score >= 90) {
  print('优秀');
} else if (score >= 60) {
  print('及格');
} else {
  print('不及格');
}

// 三元运算符
var result = score >= 60  '通过' : '补考';

这类代码不复杂,但很适合拿来熟悉 Dart 的块级结构和表达式风格。

for、for-in 和 while 分别适合什么场景

循环语句主要看你是“按次数遍历”,还是“按集合内容遍历”。

// for循环
for (var i = 0; i < 5; i++) {
  print(i);
}

// for-in循环
var fruits = ['apple', 'banana', 'orange'];
for (var fruit in fruits) {
  print(fruit);
}

// while循环
int count = 3;
while (count > 0) {
  print(count--);
}

for 更适合明确下标和次数,for-in 适合直接遍历集合元素,while 则适合依赖条件持续执行的场景。

函数定义、箭头函数与参数类型

函数是 Dart 代码复用的基础。先看普通函数和箭头函数:

// 函数定义
double calculateBMI(double weight, double height) {
  return weight / (height * height);
}

// 箭头函数
String greet(String name) => 'Hello, $name!';

void main() {
  print(calculateBMI(70, 1.75));  // 22.857
  print(greet('Bob'));           // Hello, Bob!
}

如果函数逻辑只有一行返回值,箭头函数会更简洁。接着看命名参数和可选参数:

// 命名参数
void register({String name, int age}) {
  print('$name ($age) registered');
}

// 可选参数
String say(String from, [String to]) {
  return to != null  '$from to $to' : from;
}

void main() {
  register(name: 'Alice', age: 25);
  print(say('Hello'));         // Hello
  print(say('Hi', 'there'));   // Hi to there
}

命名参数更适合字段较多、强调可读性的调用方式;可选参数则适合参数不一定总会传入的简单场景。

面向对象、集合与异常处理

类、对象与构造函数怎么入门

Dart 的面向对象写法比较直观,适合从“属性 + 构造函数 + 方法”这一最小组合开始理解。

class Person {
  String name;
  int age;
  
  // 构造函数
  Person(this.name, this.age);
  
  // 命名构造函数
  Person.newborn(String name) : this(name, 0);
  
  // 方法
  void introduce() {
    print('我是$name,今年$age岁');
  }
}

void main() {
  var p1 = Person('Alice', 25);
  var baby = Person.newborn('Charlie');
  p1.introduce();  // 我是Alice,今年25岁
}

这个例子里已经包含了 Dart 类最常见的几部分:字段、普通构造函数、命名构造函数和实例方法。理解这一层后,再继续看继承和多态会更顺。

继承、多态和 Mixin 有什么区别

继承用于扩展父类能力,多态体现为“父类类型引用子类对象”,Mixin 则更像是把一组能力组合进类中。

class Animal {
  void makeSound() => print('---');
}

class Dog extends Animal {
  @override
  void makeSound() => print('汪汪!');
}

void main() {
  Animal myPet = Dog();
  myPet.makeSound();  // 汪汪!
}
mixin Flyable {
  void fly() => print('飞行中...');
}

class Bird with Flyable {}

void main() {
  var sparrow = Bird();
  sparrow.fly();  // 飞行中...
}

入门时可以这样记:extends 是“是一种”,with 是“具备某种能力”。

集合操作和泛型该先掌握哪些

集合是日常开发的高频内容,而泛型决定了集合和类中数据的类型约束。

var numbers = [1, 2, 3];
numbers.add(4);
numbers.removeAt(0);
print(numbers.where((n) => n > 2));  // (3,4)
var capitals = {
  'China': 'Beijing',
  'Japan': 'Tokyo'
};
capitals['USA'] = 'Washington';
print(capitals.containsKey('China'));  // true
class Box {
  T content;
  Box(this.content);
}

void main() {
  var stringBox = Box('Secret');
  var intBox = Box(42);
}

List 和 Map 的增删查改是基础操作,而泛型 的意义在于让代码既能复用,又不丢失类型信息。

异常处理怎么写得更稳妥

当代码可能抛出错误时,Dart 提供了 try、on、catch 和 finally 这套完整结构。

void main() {
  try {
    var result = 100 ~/ 0;
  } on IntegerDivisionByZeroException {
    print('除数不能为零!');
  } catch (e) {
    print('未知错误: $e');
  } finally {
    print('处理完成');
  }
}

这里展示的是一个典型场景:先精确捕获已知异常,再用 catch 兜底,最后通过 finally 收尾。

异步编程、综合案例与最佳实践

Future 和 async/await 怎么配合

Dart 在异步编程上的核心是 Future。当一个操作需要等待,例如网络请求、文件读取或定时任务,就会用到它。

Future fetchUser() async {
  await Future.delayed(Duration(seconds: 1));
  return '用户数据';
}

void main() async {
  print('开始获取...');
  var user = await fetchUser();
  print('获取到:$user');
}

这段代码展示了最基础的异步流程:先声明异步函数,再在调用端使用 await 等待结果返回。

Stream 适合处理什么数据流

如果不是一次性拿到结果,而是持续按时间或事件产出数据,就更适合使用 Stream。

Stream countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    await Future.delayed(Duration(milliseconds: 500));
    yield i;
  }
}

void main() async {
  await for (var num in countStream(3)) {
    print(num);  // 间隔0.5秒输出1,2,3
  }
}

和 Future 相比,Stream 更像一个连续输出结果的管道,适合消息、计数、事件监听等场景。

综合案例:温度转换器

把前面的类、构造函数、getter 和工厂构造方法组合起来,就可以写出一个小型实用示例:

class Temperature {
  double celsius;
  
  Temperature(this.celsius);
  
  double get fahrenheit => celsius * 9/5 + 32;
  
  factory Temperature.fromFahrenheit(double f) {
    return Temperature((f - 32) * 5/9);
  }
}

void main() {
  var t1 = Temperature(25);
  print('25°C = ${t1.fahrenheit.toStringAsFixed(1)}°F');  // 77.0°F
  
  var t2 = Temperature.fromFahrenheit(77);
  print('77°F = ${t2.celsius}°C');  // 25°C
}

这个例子有两个值得注意的点:一是用 getter 提供华氏度计算结果,二是通过 factory 构造函数支持从另一种单位创建对象。

最佳实践与后续练习

如果你已经能读懂前面的代码,接下来就该开始整理开发习惯。原文给出的建议可以直接作为入门阶段的基本规范:

  1. 始终启用空安全
  2. 使用final声明不需要修改的变量
  3. 优先使用运算符处理空值
  4. 对于简单构造函数使用语法糖形式
  5. 异步操作统一使用async/await
  6. 集合操作多使用高阶函数(map, where, reduce等)

再往下一步,可以通过一个小练习把类、集合和方法串起来。原始示例是一个简易待办事项应用,虽然介绍里误写成了“深入了解HTML的应用与实践”,但实际代码仍然是 Dart:

  • 使用类管理待办事项
  • 支持添加/删除任务
  • 可以标记任务完成状态
  • 保存数据到本地文件
class TodoItem {
  String title;
  bool isDone;
  
  TodoItem(this.title, [this.isDone = false]);
}

class TodoList {
  final List _items = [];
  
  void add(String title) => _items.add(TodoItem(title));
  
  void remove(int index) => _items.removeAt(index);
  
  void toggleDone(int index) {
    _items[index].isDone = !_items[index].isDone;
  }
  
  void display() {
    _items.asMap().forEach((i, item) {
      print('${i+1}. [${item.isDone  '' : ' '}] ${item.title}');
    });
  }
}

void main() {
  var myList = TodoList();
  myList.add('学习Dart');
  myList.add('练习Flutter');
  myList.toggleDone(0);
  myList.display();
}

输出结果:

1. [] 学习Dart
2. [ ] 练习Flutter

这个练习很适合作为 Dart 入门后的第一道综合题。它覆盖了类设计、列表管理、状态切换和输出展示,也能自然过渡到文件存储、命令行交互,或者后续的 Flutter UI 开发。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多