下面从 Flutter 开发会用到的 Dart 语法 开始讲。Dart 是一门强类型、面向对象、支持空安全和异步编程的语言。Flutter 的页面、组件、状态、网络请求、路由逻辑,基本都写在 Dart 里。
- Dart 程序入口
Dart 程序从 main() 函数开始。
void main() {
print('Hello Dart');
}
Flutter 项目里也是这样:
void main() {
runApp(const MyApp());
}
解释:
void
表示函数没有返回值。
main()
是程序入口函数。
print()
用于控制台输出。
- 注释
单行注释:
// 这是单行注释
多行注释:
/*
这是多行注释
*/
文档注释:
/// 用户模型
class User {}
- 变量声明
Dart 常见变量声明方式有:
var name = 'Tom';
String title = '首页';
int age = 18;
double price = 99.5;
bool isLogin = true;
3.1 var
var 会自动推断类型。
var name = 'Tom';
等价于:
String name = 'Tom';
但类型确定后不能变:
var name = 'Tom';
name = 'Jerry'; // 可以
name = 123; // 错误,name 已经是 String
3.2 明确类型
String name = 'Tom';
int age = 18;
double score = 98.5;
bool passed = true;
这种写法更清晰,业务模型里常用。
- final 和 const
4.1 final
final 表示变量只能赋值一次。
final name = 'Tom';
name = 'Jerry'; // 错误
可以运行时赋值:
final now = DateTime.now();
因为 DateTime.now() 是运行时才知道的。
4.2 const
const 表示编译期常量。
const appName = 'Demo App';
const maxCount = 10;
不能这样:
const now = DateTime.now(); // 错误
因为当前时间不是编译期能确定的。
4.3 Flutter 中的 const
Flutter 里经常写:
const Text('Hello')
如果 Widget 内容固定,建议加 const,可以减少不必要的对象创建。
Column(
children: const [
Text('语文'),
Text('数学'),
],
)
- 基础数据类型
5.1 int
整数:
int count = 10;
int age = 18;
5.2 double
小数:
double price = 19.99;
double height = 175.5;
5.3 num
num 是 int 和 double 的父类型。
num a = 10;
num b = 3.14;
5.4 String
字符串:
String name = 'Tom';
String title = "首页";
字符串拼接:
String firstName = 'Tom';
String lastName = 'Lee';
String fullName = firstName + ' ' + lastName;
更推荐字符串模板:
String fullName = 'lastName';
表达式用 ${}:
int age = 18;
String text = '年龄是 ${age + 1}';
多行字符串:
String content = '''
第一行
第二行
第三行
''';
5.5 bool
布尔值:
bool isLogin = true;
bool isVip = false;
- 空安全 Null Safety
Dart 默认变量不能为 null。
String name = null; // 错误
如果允许为空,要加 ?:
String? name = null;
6.1 可空类型
String? nickname;
nickname = null;
nickname = 'Tom';
使用可空变量时,不能直接当非空使用:
String? name = null;
print(name.length); // 错误
因为 name 可能是 null。
6.2 null 判断
String? name = 'Tom';
if (name != null) {
print(name.length);
}
6.3 ?? 默认值
String? name;
String displayName = name ?? '匿名用户';
如果 name 是 null,就使用 '匿名用户'。
6.4 ?. 安全访问
String? name;
print(name?.length);
如果 name 是 null,结果就是 null,不会报错。
6.5 ! 强制非空
String? name = 'Tom';
print(name!.length);
! 表示“我确定它不是 null”。
但如果实际是 null,会运行时报错:
String? name = null;
print(name!.length); // 运行时报错
所以 ! 不要乱用。
6.6 late 延迟初始化
late String token;
void init() {
token = 'abc123';
}
late 表示稍后一定会赋值。
Flutter 中常见:
late TextEditingController controller;
@override
void initState() {
super.initState();
controller = TextEditingController();
}
如果使用前没有赋值,会报错。
- 运算符
7.1 算术运算
int a = 10;
int b = 3;
print(a + b); // 13
print(a - b); // 7
print(a * b); // 30
print(a / b); // 3.333...
print(a ~/ b); // 3,整除
print(a % b); // 1,取余
7.2 比较运算
print(a == b);
print(a != b);
print(a > b);
print(a >= b);
print(a < b);
print(a <= b);
7.3 逻辑运算
bool isLogin = true;
bool isVip = false;
print(isLogin && isVip); // 并且
print(isLogin || isVip); // 或者
print(!isLogin); // 取反
7.4 赋值运算
int count = 1;
count += 1;
count -= 1;
count *= 2;
7.5 ??=
如果变量为 null,才赋值:
String? name;
name ??= '匿名用户';
print(name); // 匿名用户
- 条件语句
8.1 if else
int score = 85;
if (score >= 90) {
print('优秀');
} else if (score >= 60) {
print('及格');
} else {
print('不及格');
}
8.2 三元表达式
bool isLogin = true;
String text = isLogin ? '已登录' : '未登录';
Flutter 中常用:
Text(isLogin ? '退出登录' : '登录')
8.3 switch
String role = 'teacher';
switch (role) {
case 'admin':
print('管理员');
break;
case 'teacher':
print('老师');
break;
default:
print('普通用户');
}
- 循环
9.1 for
for (int i = 0; i < 5; i++) {
print(i);
}
9.2 for in
List<String> names = ['Tom', 'Jerry'];
for (final name in names) {
print(name);
}
9.3 while
int count = 0;
while (count < 3) {
print(count);
count++;
}
9.4 do while
int count = 0;
do {
print(count);
count++;
} while (count < 3);
- List 列表
List 类似数组。
List<String> names = ['Tom', 'Jerry', 'Alice'];
也可以简写:
final names = ['Tom', 'Jerry', 'Alice'];
10.1 常用操作
names.add('Bob');
names.remove('Tom');
names.removeAt(0);
print(names.length);
print(names[0]);
10.2 遍历
for (final name in names) {
print(name);
}
names.forEach((name) {
print(name);
});
10.3 map 转换
final upperNames = names.map((name) {
return name.toUpperCase();
}).toList();
简写:
final upperNames = names.map((name) => name.toUpperCase()).toList();
10.4 where 过滤
final longNames = names.where((name) => name.length > 3).toList();
10.5 firstWhere
final user = users.firstWhere((user) => user.id == 1);
如果可能找不到,建议:
final user = users.where((user) => user.id == 1).firstOrNull;
不过 firstOrNull 需要额外扩展包,基础 Dart 里可以这样:
User? found;
for (final user in users) {
if (user.id == 1) {
found = user;
break;
}
}
- Set 集合
Set 不允许重复。
Set<int> ids = {1, 2, 3, 3};
print(ids); // {1, 2, 3}
常用:
ids.add(4);
ids.remove(2);
print(ids.contains(1));
- Map 字典
Map 是键值对。
Map<String, dynamic> user = {
'id': 1,
'name': 'Tom',
'age': 18,
};
读取:
print(user['name']);
修改:
user['name'] = 'Jerry';
判断:
print(user.containsKey('name'));
遍历:
user.forEach((key, value) {
print('value');
});
Flutter 网络请求 JSON 经常用:
Map<String, dynamic> json = {
'username': 'tom',
'password': '123456',
};
- 函数
13.1 普通函数
int add(int a, int b) {
return a + b;
}
调用:
final result = add(1, 2);
13.2 无返回值
void log(String message) {
print(message);
}
13.3 箭头函数
函数体只有一行时:
int add(int a, int b) => a + b;
等价于:
int add(int a, int b) {
return a + b;
}
13.4 可选位置参数
void sayHello(String name, [String? prefix]) {
print('name');
}
调用:
sayHello('Tom');
sayHello('Tom', 'Hello');
13.5 命名参数
Flutter 里大量使用命名参数。
void createUser({
required String name,
int age = 18,
}) {
print('age');
}
调用:
createUser(name: 'Tom');
createUser(name: 'Tom', age: 20);
required 表示必传。
默认值:
int age = 18
13.6 函数作为参数
void runTask(void Function() task) {
task();
}
runTask(() {
print('执行任务');
});
带参数:
void each(List<String> list, void Function(String item) callback) {
for (final item in list) {
callback(item);
}
}
调用:
each(['A', 'B'], (item) {
print(item);
});
这就是高阶函数。
- 类 class
14.1 定义类
class User {
String name;
int age;
User(this.name, this.age);
void sayHello() {
print('Hello, $name');
}
}
使用:
final user = User('Tom', 18);
user.sayHello();
14.2 命名参数构造函数
Flutter 项目里更常用:
class User {
final int id;
final String name;
final int age;
User({
required this.id,
required this.name,
required this.age,
});
}
创建:
final user = User(
id: 1,
name: 'Tom',
age: 18,
);
14.3 final 属性
class User {
final int id;
final String name;
User({
required this.id,
required this.name,
});
}
final 表示创建后不能改:
user.name = 'Jerry'; // 错误
Flutter 数据模型常用不可变对象。
14.4 方法
class User {
final String name;
User(this.name);
String getDisplayName() {
return '用户:$name';
}
}
14.5 getter
class User {
final String firstName;
final String lastName;
User(this.firstName, this.lastName);
String get fullName => 'lastName';
}
调用:
print(user.fullName);
像属性一样访问。
14.6 setter
class Counter {
int _value = 0;
set value(int newValue) {
if (newValue >= 0) {
_value = newValue;
}
}
int get value => _value;
}
- 私有成员
Dart 没有 private 关键字,用 _ 开头表示库内私有。
class UserService {
String _token = '';
void _refreshToken() {
print('刷新 token');
}
}
_token 和 _refreshToken 在当前文件库外不可访问。
Flutter 里常见:
class _HomePageState extends State<HomePage> {}
- 继承 extends
class Animal {
void eat() {
print('吃东西');
}
}
class Dog extends Animal {
void bark() {
print('汪汪');
}
}
使用:
final dog = Dog();
dog.eat();
dog.bark();
16.1 重写方法
class Dog extends Animal {
@override
void eat() {
print('狗在吃东西');
}
}
@override 表示重写父类方法。
Flutter 里:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}
- 抽象类 abstract
abstract class ApiService {
Future<String> getData();
}
子类必须实现:
class UserService extends ApiService {
@override
Future<String> getData() async {
return 'user data';
}
}
- implements 接口实现
Dart 里每个类都可以当接口。
class Logger {
void log(String message) {}
}
class ConsoleLogger implements Logger {
@override
void log(String message) {
print(message);
}
}
implements 要实现所有成员。
- mixin 混入
mixin 用于复用一组方法。
mixin LoggerMixin {
void log(String message) {
print('[LOG] $message');
}
}
class UserService with LoggerMixin {
void getUser() {
log('获取用户');
}
}
Flutter 中很多状态类会用 mixin,比如动画:
class _PageState extends State<Page>
with SingleTickerProviderStateMixin {
}
- enum 枚举
enum LoginStatus {
loggedOut,
loggingIn,
loggedIn,
}
使用:
LoginStatus status = LoginStatus.loggedOut;
if (status == LoginStatus.loggedIn) {
print('已登录');
}
Flutter 中可以控制 UI 状态:
switch (status) {
case LoginStatus.loggedOut:
return LoginPage();
case LoginStatus.loggingIn:
return LoadingView();
case LoginStatus.loggedIn:
return HomePage();
}
- 泛型
泛型就是把类型作为参数。
class ApiResult<T> {
final int code;
final String message;
final T data;
ApiResult({
required this.code,
required this.message,
required this.data,
});
}
使用:
final result = ApiResult<User>(
code: 200,
message: 'success',
data: user,
);
列表也是泛型:
List<String> names = [];
Map<String, dynamic> json = {};
泛型方法:
T getFirst<T>(List<T> list) {
return list.first;
}
调用:
final name = getFirst<String>(['Tom', 'Jerry']);
final age = getFirst<int>([18, 20]);
- Future 异步
Flutter 网络请求、读文件、数据库、本地存储都大量使用异步。
Future<String> fetchData() async {
await Future.delayed(const Duration(seconds: 1));
return '数据';
}
调用:
void load() async {
final data = await fetchData();
print(data);
}
22.1 async / await
Future<void> login() async {
print('开始登录');
final token = await requestLogin();
print('token: $token');
}
await 只能在 async 函数里用。
22.2 try catch
Future<void> loadUser() async {
try {
final user = await fetchUser();
print(user.name);
} catch (e) {
print('请求失败:$e');
}
}
- Stream 流
Stream 表示一连串异步数据。
Stream<int> countStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
监听:
countStream().listen((value) {
print(value);
});
Flutter 中常见于:
WebSocket
蓝牙数据
定位变化
表单输入变化
Firebase 数据
- 异常处理
抛异常:
throw Exception('登录失败');
捕获:
try {
await login();
} catch (e) {
print(e);
}
自定义异常:
class ApiException implements Exception {
final String message;
ApiException(this.message);
@override
String toString() => message;
}
使用:
throw ApiException('Token 已过期');
- import 导入
导入系统库:
import 'dart:convert';
导入第三方包:
import 'package:dio/dio.dart';
导入项目文件:
import '../models/user.dart';
Flutter 中:
import 'package:flutter/material.dart';
- JSON 转模型
后端返回 JSON:
{
"id": 1,
"name": "Tom",
"age": 18
}
Dart 模型:
class User {
final int id;
final String name;
final int age;
User({
required this.id,
required this.name,
required this.age,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'] ?? '',
age: json['age'] ?? 0,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'age': age,
};
}
}
使用:
final user = User.fromJson(response.data);
final json = user.toJson();
列表转换:
final users = (data as List)
.map((item) => User.fromJson(item))
.toList();
更严谨一点:
final users = (data as List<dynamic>)
.map((item) => User.fromJson(item as Map<String, dynamic>))
.toList();
- Flutter 中最常见的 Dart 写法
27.1 StatelessWidget
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return const Text('首页');
}
}
解释:
class HomePage extends StatelessWidget
定义一个无状态组件。
const HomePage({super.key});
构造函数,传递 key 给父类。
Widget build(BuildContext context)
返回 UI。
27.2 StatefulWidget
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('数量:$count'),
ElevatedButton(
onPressed: () {
setState(() {
count++;
});
},
child: const Text('增加'),
),
],
);
}
}
这里涉及:
类
继承
泛型
私有类
状态变量
回调函数
setState
Widget 树
- 常见 Widget 参数语法
Flutter 大量使用命名参数。
Container(
width: 100,
height: 100,
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(top: 20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
),
child: const Text('Hello'),
)
这些都是命名参数:
width:
height:
padding:
margin:
decoration:
child:
child 表示一个子组件。
children 表示多个子组件:
Column(
children: const [
Text('A'),
Text('B'),
],
)
- 回调函数语法
按钮点击:
ElevatedButton(
onPressed: () {
print('点击');
},
child: const Text('提交'),
)
onPressed 接收一个函数。
如果按钮禁用:
ElevatedButton(
onPressed: null,
child: const Text('提交'),
)
带参数的回调:
TextField(
onChanged: (value) {
print(value);
},
)
- async 在 UI 中的使用
ElevatedButton(
onPressed: () async {
final result = await login();
print(result);
},
child: const Text('登录'),
)
网络请求:
Future<void> loadData() async {
try {
final user = await UserService.getUserInfo();
setState(() {
this.user = user;
});
} catch (e) {
setState(() {
errorMessage = e.toString();
});
}
}
- 扩展方法 extension
可以给已有类型扩展方法。
extension StringExt on String {
bool get isPhone {
return RegExp(r'^1\d{10}$').hasMatch(this);
}
}
使用:
final phone = '13800138000';
print(phone.isPhone);
Flutter 项目里可用于格式化:
extension DateTimeExt on DateTime {
String get yyyyMMdd {
return 'month-$day';
}
}
- typedef 类型别名
给函数类型起别名。
typedef ValueChanged<T> = void Function(T value);
自定义:
typedef LoginCallback = void Function(String token);
使用:
class LoginButton {
final LoginCallback onLogin;
LoginButton({required this.onLogin});
}
Flutter 内部也大量使用类似写法。
- cascade 级联操作符 ..
可以连续操作同一个对象。
final list = <String>[]
..add('A')
..add('B')
..add('C');
等价于:
final list = <String>[];
list.add('A');
list.add('B');
list.add('C');
对象配置:
final dio = Dio()
..options.baseUrl = 'https://api.example.com'
..options.connectTimeout = const Duration(seconds: 10);
- as / is 类型判断
34.1 is
if (value is String) {
print(value.length);
}
34.2 as
final map = data as Map<String, dynamic>;
如果类型不对,会报错。
安全点可以先判断:
if (data is Map<String, dynamic>) {
print(data['name']);
}
- Dart 在 Flutter 里的学习重点
如果你是为了 Flutter,优先掌握这些:
变量:var / final / const
空安全:? / ?? / ?. / !
函数:命名参数、required、回调函数
类:构造函数、final 属性、fromJson
集合:List / Map / Set
异步:Future / async / await / try catch
泛型:List<T> / ApiResult<T>
继承:extends StatelessWidget / StatefulWidget
状态:setState
导入:import
最小综合例子
import 'package:flutter/material.dart';
class User {
final int id;
final String name;
User({
required this.id,
required this.name,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] ?? 0,
name: json['name'] ?? '',
);
}
}
Future<User> fetchUser() async {
await Future.delayed(const Duration(seconds: 1));
final json = {
'id': 1,
'name': 'Tom',
};
return User.fromJson(json);
}
class UserPage extends StatefulWidget {
const UserPage({super.key});
@override
State<UserPage> createState() => _UserPageState();
}
class _UserPageState extends State<UserPage> {
User? user;
bool loading = false;
@override
void initState() {
super.initState();
loadUser();
}
Future<void> loadUser() async {
setState(() {
loading = true;
});
final result = await fetchUser();
setState(() {
user = result;
loading = false;
});
}
@override
Widget build(BuildContext context) {
if (loading) {
return const CircularProgressIndicator();
}
return Text(user?.name ?? '暂无用户');
}
}
这个例子覆盖了 Flutter 开发最常见的 Dart 语法:
import
class
final
构造函数
factory
Map
Future
async/await
StatefulWidget
泛型 State<UserPage>
可空类型 User?
setState
?? 默认值
学 Flutter 的 Dart,不需要一开始钻特别深的语言细节。先把这些语法吃透,就可以开始写页面、调接口、做登录、做列表和详情页了。