Flutter从入门到实战-01-Dart语言基础

Flutter 从入门到实战(一):Dart 语言基础

面向刚接触 Flutter 的同学。内容以"能快速上手、适合发布博客"为目标,重新组织了章节结构与表达方式。

一、为什么要学 Flutter

Flutter 是 Google 开源的一套跨平台 UI 开发工具包,目标是使用一套代码,构建接近原生体验的多端应用。

它的价值主要体现在 3 个方面:

  1. 开发效率高

    一套 Dart 代码可以同时面向 Android、iOS、Web、Windows,甚至更多平台。

  2. 性能与体验更均衡

    Flutter 直接控制渲染层,在很多场景下能获得比较流畅的界面表现。

  3. 企业落地广

    课程讲义中提到,Flutter 在跨平台方案中拥有很高的采用率,已经有大量实际应用落地。

如果你想做跨端应用,但又不想分别深入 Android 和 iOS 原生开发,Flutter 是一个很值得投入的方向。

二、这套课程在讲什么

这份讲义整体是一个渐进式学习路径,核心分为 3 个部分:

  1. Dart 语言基础
  2. Flutter 组件核心
  3. 综合案例实战

其中第一份讲义的重点,主要是帮助我们先把 Dart 打牢。原因很简单:Flutter 的开发语言就是 Dart,如果语言基础不稳,后面的组件、状态、网络请求、项目结构都会学得很吃力。

三、开始前需要准备什么

1. 安装 Dart SDK

Dart SDK 是 Dart 官方提供的工具包,负责代码编写、运行、调试和编译。

我们可以把它理解为:想学 Flutter,先把 Dart 的运行环境准备好。

2. 准备编辑器

讲义中推荐了支持 AI 能力的编辑器 Trae,并提到两种常见工作方式:

  1. Tab 补全模式

    编写代码时,AI 根据上下文自动补全。

  2. Builder 协作模式

    直接用自然语言描述需求,让 AI 协助生成或修改代码。

不管你最终使用哪款编辑器,建议至少具备以下能力:

  1. Dart 语法高亮
  2. 自动补全
  3. 报错提示
  4. 运行与调试支持

3. Dart 初学者注意事项

刚开始写 Dart 时,先记住这几个基本规则:

  1. 文件后缀是 .dart
  2. 程序入口通常是 main()
  3. 大多数语句需要以分号结尾
  4. 大括号后的语法规则要和其他现代语言区分清楚

一个最简单的 Dart 程序如下:

dart 复制代码
void main() {
  print('Hello Dart');
}

四、变量与常量:先搞清楚"值会不会变"

在 Dart 中,最先要理解的是变量和常量的区别。

1. var:用于声明变量

当一个值后续还会变化时,使用 var。

dart 复制代码
void main() {
  var age = 20;
  age = 21;
  print(age);
}

特点:

  1. Dart 会根据初始值自动推断类型
  2. 类型一旦推断完成,就不能随意改成别的类型
dart 复制代码
void main() {
  var name = 'Tom';
  // name = 18; // 会报错,因为 name 已经被推断为 String
}

2. const:编译时常量

如果一个值从定义开始就不会变化,并且在编译阶段就能确定,使用 const。

dart 复制代码
void main() {
  const pi = 3.1415926;
  print(pi);
}

适用场景:

  1. 固定配置
  2. 数学常量
  3. 永远不会变化的字面量

3. final:运行时常量

如果一个值只会赋值一次,但这个值要等到运行时才能确定,就使用 final。

dart 复制代码
void main() {
  final now = DateTime.now();
  print(now);
}

4. var、const、final 怎么选

可以直接记住这套判断逻辑:

  1. 值会变:用 var
  2. 值不变,且编译时确定:用 const
  3. 值不变,但运行时才确定:用 final

五、Dart 常用数据类型

讲义重点介绍了 6 类常用数据类型:

  1. String
  2. int
  3. double
  4. num
  5. bool
  6. List
  7. Map
  8. dynamic

1. 字符串 String

字符串用于描述文本内容。

dart 复制代码
void main() {
  String title = 'Flutter 入门';
  print(title);
}
模板字符串

模板字符串是 Dart 中非常常用的能力:

dart 复制代码
void main() {
  String mealTime = '早上 8 点';
  String text = '我要在 $mealTime 的时候吃早饭';
  print(text);
}

如果是表达式,可以写成 ${表达式}:

dart 复制代码
void main() {
  int a = 10;
  int b = 20;
  print('总和是 ${a + b}');
}

2. 数字类型 int、double、num

它们的区别可以简单理解为:

  1. int:整数
  2. double:浮点数
  3. num:既可以表示整数,也可以表示小数
dart 复制代码
void main() {
  int age = 18;
  double score = 98.5;
  num price = 100;
  price = 99.9;
}

需要注意的是,不同数字类型之间并不是所有情况都能直接互相赋值,这一点在实际编码中要格外小心。

3. 布尔类型 bool

布尔类型只有两个值:true 和 false。

dart 复制代码
void main() {
  bool finishedHomework = true;
  print(finishedHomework);
}

4. 列表类型 List

当一个变量要保存多个值时,通常使用 List。

dart 复制代码
void main() {
  List<String> students = ['小明', '小红', '小刚'];
  print(students);
}

常用操作包括:

  1. add():尾部添加元素
  2. addAll():追加一组元素
  3. remove():删除指定元素
  4. removeLast():删除最后一个元素
  5. forEach():遍历
  6. where():筛选
  7. every():判断是否全部满足条件

示例:

dart 复制代码
void main() {
  List<int> scores = [88, 92, 75, 99];
  scores.add(100);

  var goodScores = scores.where((item) => item >= 90);
  print(goodScores.toList());
}

5. 字典类型 Map

Map 用于保存键值对数据。

dart 复制代码
void main() {
  Map<String, String> dict = {
    'apple': '苹果',
    'banana': '香蕉',
  };

  print(dict['apple']);
}

常见操作有:

  1. forEach()
  2. addAll()
  3. containsKey()
  4. remove()
  5. clear()

6. 动态类型 dynamic

dynamic 表示动态类型,变量在运行时可以自由改变类型。

dart 复制代码
void main() {
  dynamic value = 'hello';
  value = 123;
  value = true;
  print(value);
}

但要注意,dynamic 会绕过很多编译期检查。也就是说,它虽然灵活,但会降低代码的安全性和可维护性。

dynamic 和 var 的区别

这是初学者特别容易混淆的一点:

  1. var 是类型推断,不是动态类型
  2. dynamic 才是真正意义上的"运行时再决定类型"

简化理解:

dart 复制代码
void main() {
  var a = 'hello';
  // a = 123; // 不允许

  dynamic b = 'hello';
  b = 123; // 允许
}

实际开发里,能不用 dynamic 就尽量不用。

六、空安全:Dart 非常重要的一道保护

空安全是 Dart 很重要的特性,它的核心目标是把很多空指针问题提前到编译阶段暴露出来,而不是等程序跑起来再崩。

1. 可空与不可空

默认情况下,类型是不可为空的:

dart 复制代码
String name = 'Flutter';

如果允许为空,要加 ?:

dart 复制代码
String? name;

2. 常见空安全操作

常用写法包括:

  1. ?:声明可空类型
  2. ?.:空值安全调用
  3. !:非空断言
  4. ??:空值兜底
  5. ??=:当变量为空时再赋值

示例:

dart 复制代码
void main() {
  String? nickname;

  print(nickname?.length);
  print(nickname ?? '默认昵称');

  nickname ??= '游客';
  print(nickname);
}

! 虽然可以强制告诉编译器"这里一定不为空",但使用时一定要谨慎,否则还是可能在运行时报错。

七、运算符:写逻辑的基础

讲义中把常见运算符分成 4 类:

  1. 算术运算符
  2. 赋值运算符
  3. 比较运算符
  4. 逻辑运算符

1. 算术运算符

常见有:

  1. +
  2. -
  3. *
  4. /
  5. ~/:整除
  6. %:取余
dart 复制代码
void main() {
  print(7 / 2);   // 3.5
  print(7 ~/ 2);  // 3
  print(7 % 2);   // 1
}

2. 赋值运算符

常见有:

  1. =
  2. +=
  3. -=
  4. *=
  5. /=
  6. %=

3. 比较运算符

比较运算结果一定是布尔值:

  1. ==
  2. !=
  3. >
  4. <
  5. >=
  6. <=

4. 逻辑运算符

用于处理布尔表达式:

  1. &&:并且
  2. ||:或者
  3. !:取反
dart 复制代码
void main() {
  bool isAdult = true;
  bool hasTicket = false;

  print(isAdult && hasTicket);
}

八、流程控制:让程序能"判断"和"循环"

1. if 分支

if 用于条件判断,是最基础的控制结构。

dart 复制代码
void main() {
  int score = 85;

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

2. 三元运算符

适合简化双分支逻辑:

dart 复制代码
void main() {
  int age = 20;
  String result = age >= 18 ? '成年人' : '未成年';
  print(result);
}

3. switch / case

当条件很多,而且本质上是在做"相等判断"时,switch 会更清晰。

dart 复制代码
void main() {
  String level = 'vip';

  switch (level) {
    case 'vip':
      print('高级会员');
      break;
    case 'normal':
      print('普通会员');
      break;
    default:
      print('游客');
  }
}

4. while 循环

while 适合"只要条件满足就一直执行"的场景。

dart 复制代码
void main() {
  int i = 0;

  while (i < 3) {
    print(i);
    i++;
  }
}

5. for 循环

for 是最常见的循环结构之一,也很适合遍历集合。

dart 复制代码
void main() {
  List<String> names = ['A', 'B', 'C'];

  for (int i = 0; i < names.length; i++) {
    print(names[i]);
  }
}

九、函数:把重复逻辑封装起来

函数是 Dart 代码组织和复用的核心能力。

1. 基本定义

dart 复制代码
int add(int a, int b) {
  return a + b;
}

2. 返回值

函数可以有返回值,也可以没有返回值:

dart 复制代码
int sum(int a, int b) {
  return a + b;
}

void logMessage() {
  print('hello');
}

3. 必传参数

dart 复制代码
String getUserName(String name) {
  return name;
}

4. 可选位置参数

使用中括号包裹:

dart 复制代码
String joinName(String first, [String? second]) {
  return '$first ${second ?? ''}';
}

适合参数顺序明确、可省略的场景。

5. 可选命名参数

使用大括号包裹,并通过"参数名: 值"的方式传参:

dart 复制代码
String createUser(String name, {int? age, String? city}) {
  return '$name - ${age ?? 0} - ${city ?? '未知'}';
}

void main() {
  print(createUser('Tom', age: 20, city: 'Shanghai'));
}

这种写法在 Flutter 中非常常见,因为可读性更好。

6. 匿名函数

匿名函数没有名字,常用于回调场景。

dart 复制代码
void main() {
  List<int> list = [1, 2, 3];

  list.forEach((item) {
    print(item);
  });
}

7. 箭头函数

当函数体只有一行时,可以用箭头函数简化:

dart 复制代码
int square(int x) => x * x;

十、类与面向对象:Flutter 开发绕不开的基础

Flutter 中大量代码都建立在类和对象之上,所以 Dart 的面向对象能力必须理解。

1. 定义类

dart 复制代码
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  void study() {
    print('$name 正在学习');
  }
}

2. 构造函数

讲义中提到 3 类常见构造方式:

  1. 默认构造函数
  2. 命名构造函数
  3. 构造函数语法糖
默认构造函数
dart 复制代码
class Person {
  String name;
  int age;

  Person(this.name, this.age);
}
命名构造函数
dart 复制代码
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  Person.guest()
      : name = '游客',
        age = 0;
}

3. 公有与私有成员

Dart 中以下划线开头的属性或方法,通常表示私有成员。

dart 复制代码
class User {
  String name = 'Tom';
  String _token = 'abc123';
}

4. 继承

Dart 是单继承语言,一个类只能有一个直接父类。

dart 复制代码
class Animal {
  void run() {
    print('动物在跑');
  }
}

class Dog extends Animal {
  @override
  void run() {
    print('小狗在跑');
  }
}

5. 多态

多态的核心是:同样的调用,面对不同对象时,会有不同实现。

这通常通过继承和方法重写来体现。

6. 抽象类与接口实现

当你只想约束规范,而不直接提供完整实现时,可以使用抽象类:

dart 复制代码
abstract class Pay {
  void pay();
}

class WechatPay implements Pay {
  @override
  void pay() {
    print('微信支付');
  }
}

7. 混入 mixin

如果你想在不走传统继承链的情况下,为类扩展能力,可以使用 mixin。

dart 复制代码
mixin Runner {
  void run() {
    print('running');
  }
}

class Person with Runner {}

8. 泛型

泛型的价值是:既限制类型,又保留复用能力。

dart 复制代码
class Box<T> {
  T value;
  Box(this.value);
}

void main() {
  Box<String> box = Box<String>('hello');
  print(box.value);
}

十一、异步编程:Dart 处理耗时任务的方式

异步编程是 Flutter 开发里的高频内容,因为网络请求、文件读写、数据库访问都离不开它。

1. 事件循环

讲义中强调了一个关键点:Dart 是单线程模型,但它通过事件循环机制来协调同步任务和异步任务。

可以简单理解为:

  1. 先执行主线程中的同步代码
  2. 遇到耗时任务时,不阻塞主流程
  3. 等异步结果准备好后,再回到事件循环中处理

2. Future

Future 表示一个未来才会拿到结果的异步操作。

dart 复制代码
Future<String> getData() async {
  return '请求成功';
}

它通常有几种状态:

  1. 等待中
  2. 成功完成
  3. 失败完成

3. 链式调用

可以使用 then() 和 catchError() 处理结果:

dart 复制代码
Future<String> getData() async {
  return 'ok';
}

void main() {
  getData()
      .then((value) {
        print(value);
      })
      .catchError((e) {
        print(e);
      });
}

4. async / await

相比链式调用,async / await 更接近同步代码的书写方式,可读性通常更好。

dart 复制代码
Future<String> getData() async {
  return 'ok';
}

void main() async {
  try {
    String result = await getData();
    print(result);
  } catch (e) {
    print(e);
  }
}

对于 Flutter 初学者来说,建议优先把 Future 和 async / await 熟练掌握,因为后续请求接口、初始化数据、处理用户动作时都会频繁用到。

十二、学完这一讲,应该掌握什么

如果这份 Dart 基础讲义已经吸收得比较扎实,你至少应该具备下面这些能力:

  1. 能看懂并编写简单的 Dart 程序
  2. 能区分 var、const、final
  3. 能熟练使用 String、List、Map 等常见类型
  4. 理解空安全的基本规则与常见操作符
  5. 能使用分支、循环、函数组织基础逻辑
  6. 能理解类、构造函数、继承、多态、泛型等面向对象概念
  7. 能读懂并书写基本异步代码

十三、从 Dart 过渡到 Flutter,下一步学什么

Dart 基础打好之后,接下来进入 Flutter 会顺畅很多。下一阶段建议重点关注这些内容:

  1. Flutter 环境配置
  2. 工程目录结构
  3. main.dart 入口文件
  4. StatelessWidget 与 StatefulWidget
  5. 常见基础组件
  6. 页面布局与滚动容器
  7. 生命周期与状态更新

也就是说,Dart 解决的是"语言怎么写"的问题,而 Flutter 解决的是"界面怎么搭、交互怎么跑、项目怎么组织"的问题。

结语

很多人一学 Flutter 就急着写页面、搭项目、调接口,结果一遇到状态更新、空安全报错、回调函数、异步逻辑就开始混乱。根本原因往往不是 Flutter 太难,而是 Dart 基础不够稳。

真正高效的学习顺序应该是:

  1. 先把 Dart 语言基础打牢
  2. 再进入 Flutter 组件与项目开发
  3. 最后通过综合案例把知识串起来

如果你准备系统学习 Flutter,这一讲最值得反复练习的内容有 3 块:

  1. 变量与数据类型
  2. 函数与类
  3. 空安全与异步编程

把这 3 块吃透,后面学习 Flutter 会轻松很多。

相关推荐
2601_949970696 小时前
HumanizeDuration 跨端三方库仓颉适配全流程
前端·javascript·flutter
传奇开心果编程8 小时前
【Flutter踩坑排雷】第3课:const 误用坑|const 错误使用引发 UI 异常与性能损耗
flutter·移动开发·跨平台·dart·编程语言理论·编程框架·声明式ui
程序员老刘10 小时前
你的Flutter项目要不要紧急升级3.47.8?
flutter·客户端
Talyra4212 小时前
不想开会员,我写了一个记账 App
flutter
2601_9495758616 小时前
JSON5 跨端三方库仓颉适配全流程
前端·javascript·flutter
法的空间17 小时前
AI 编程时代,为什么 Dart 分析会拖慢大型项目的开发
android·flutter·ios
恋猫de小郭19 小时前
Flutter 紧急发布 3.47.8 安全升级版本,建议都升级
android·前端·flutter
好的佩奇1 天前
Dart 之模式
android·flutter·dart
淡淡的香烟2 天前
Flutter实现多语言切换
android·flutter·1024程序员节
事圆则缓2 天前
从零搭建一套 Flutter 架构:先跑通数据流
flutter