速查 02 · Dart
按问题索引。Ctrl+F 页内搜索。 系统学习见 01 篇 Dart 语言基础、06 篇 异步与进阶语法。
目录
变量与空安全
dart
final name = 'Tom'; // 运行时确定,只能赋值一次(推荐默认用 final)
const pi = 3.14; // 编译期常量
var count = 0; // 可变(尽量少用)
late final Data data; // 延迟初始化(声明时不赋值,使用前必须赋值)
String? maybeNull; // 可空类型
// 空安全三剑客
maybeNull?.length // 为 null 时整体返回 null,不报错
maybeNull ?? 'default' // 为 null 时取默认值
maybeNull! // 强制解包(为 null 就崩,慎用)
maybeNull ??= 'init'; // 为 null 时赋值
// 条件赋值 / 判空后调用
if (maybeNull case final v?) { use(v); } // 模式匹配(Dart 3)
final len = maybeNull?.length ?? 0;实践原则:能用 final 就不用 var;能不用 ! 就不用——! 是运行时崩溃的主要来源。
字符串
dart
// 插值
'Hello $name' // 简单变量
'Total: ${a + b}' // 表达式
// 多行
'''line1
line2'''
// 原始字符串(不转义,写正则/路径很方便)
r'\d+\.\d+'
// 常用操作
str.split(',') // 分割
str.trim() // 去首尾空格
str.contains('abc') // 包含
str.startsWith('a') // 前缀
str.replaceAll('a', 'b') // 替换
str.substring(0, 3) // 截取
str.padLeft(2, '0') // 补零 → "07"
str.toLowerCase() / str.toUpperCase()
// 拼接用 + 或相邻字符串字面量
'abc' 'def' // → 'abcdef'(自动连接)集合操作
dart
final list = <String>['a', 'b', 'c'];
final map = <String, int>{'a': 1};
final set = <String>{'a', 'b'};
// List 高频
list.map((e) => e.toUpperCase()).toList() // 转换
list.where((e) => e.length > 1).toList() // 过滤
list.firstWhere((e) => e == 'a', orElse: () => '')
list.expand((e) => [e, e]).toList() // 展开
list.any((e) => e.isEmpty) // 任一满足
list.every((e) => e.isNotEmpty) // 全部满足
list.fold(0, (sum, e) => sum + e.length) // 归约
list.sort((a, b) => a.compareTo(b)) // 排序
list.reversed.toList() // 反转
list.take(3) / list.skip(2) // 取前 N / 跳过前 N
list.join(',') // 转字符串
[...list1, ...list2] // 展开合并
list.asMap().entries // 带索引遍历
list.indexed // Dart 3:(index, element)
// Map 高频
map['key'] ?? 0 // 安全取值
map.containsKey('key')
map.putIfAbsent('k', () => 1)
map.entries.map((e) => '${e.key}=${e.value}')
{...map1, ...map2} // 合并(后者覆盖)
// 集合内的 if / for(Dart 特色,写 UI 极方便)
Column(children: [
const Header(),
if (isLoading) const Loading(), // 条件
for (final item in items) Tile(item), // 循环
])类与构造
dart
class User {
final String name;
final int age;
const User({required this.name, this.age = 0}); // 命名参数 + 默认值
// 命名构造
User.guest() : name = 'guest', age = 0;
// 工厂构造(可返回缓存/子类)
factory User.fromJson(Map<String, dynamic> j) =>
User(name: j['name'], age: j['age'] ?? 0);
// getter
bool get isAdult => age >= 18;
// 拷贝
User copyWith({String? name}) => User(name: name ?? this.name, age: age);
@override
String toString() => 'User($name, $age)';
}
// 级联(链式配置,省临时变量)
final user = User(name: 'Tom')..age = 18;
final sb = StringBuffer()..write('a')..write('b');
// 继承 / 混入 / 实现 的顺序
class A extends B with C implements D {}本项目用 Freezed 生成
copyWith/==/fromJson,手写仅限简单类,见 01 篇。
函数与语法糖
dart
// 箭头函数(单行)
int add(int a, int b) => a + b;
// 命名参数 vs 位置参数
void f({required String a, int b = 1}) {} // 命名(调用 f(a: 'x'))
void g(String a, [int b = 1]) {} // 可选位置(调用 g('x', 2))
// 级联 / 空安全级联
obj..a = 1..b = 2;
obj?..a = 1; // obj 为 null 则整体跳过
// 展开运算符
final args = <String>['a', ...moreArgs];
// 模式匹配(Dart 3)
switch (obj) {
case [int a, int b] when a > b: ... // 解构 List + 守卫
case {'name': String n}: print(n); // 解构 Map
case User(:final name): print(name); // 解构对象
default: ...
}
if (json case {'code': 0, 'data': final d}) { use(d); } // if-case
// Records(Dart 3,多返回值)
(int, String) f() => (1, 'a');
final (n, s) = f(); // 解构异步
dart
// async/await
Future<Data> load() async {
final r = await api.fetch();
return r;
}
// 并发(同时发起,总耗时取最慢)
final results = await Future.wait([api.a(), api.b()]);
final (a, b) = await (api.a(), api.b()).wait; // Dart 3 Records 写法
// 错误处理
try { await api.fetch(); } catch (e, s) { log(e, s); } finally { ... }
final r = await api.fetch().catchError((e) => fallback);
// 超时 / 延迟
await Future.delayed(const Duration(milliseconds: 300));
await api.fetch().timeout(const Duration(seconds: 10));
// Stream
stream.listen((v) {}, onError: (e) {}, onDone: () {});
await for (final v in stream) { print(v); }
stream.map((e) => e * 2).where((e) => e > 1)
streamController.add(v); await streamController.close(); // 记得关闭
// 只执行一次(缓存结果)
late final _cached = api.fetch(); // 天然单例异步
// 不阻塞 UI 的重计算 → Isolate
final r = await Isolate.run(() => heavyCompute());事件循环/微任务原理见 06 篇。
类型与转换
dart
int.parse('42')
double.parse('3.14')
num.tryParse('abc') // 失败返回 null(推荐,不抛异常)
42.toString()
3.14159.toStringAsFixed(2) // "3.14"
(3.7).round() / .floor() / .ceil()
// 类型判断与转换
if (x is String) { x.length; } // is 后自动提升类型
x as String // 强制转换(失败抛异常)
x is! String // 否定
// JSON
import 'dart:convert';
jsonEncode(obj) // 对象 → 字符串
jsonDecode(str) // 字符串 → Map/List
jsonDecode(str) as Map<String, dynamic>
// 时间
DateTime.now()
DateTime.parse('2026-09-03')
d.add(const Duration(days: 1))
d.difference(other).inDays
DateFormat('yyyy-MM-dd').format(d) // intl 包常用模式
dart
// 单例
class Repo { Repo._(); static final instance = Repo._(); }
// 枚举带值(Dart 2.17+)
enum Status { loading, ok('成功'), err('失败');
const Status([this.label]); final String? label; }
// extension(给现有类型加方法)
extension StringX on String {
bool get isPhone => RegExp(r'^1\d{10}$').hasMatch(this);
}
// sealed class(Dart 3,配合 switch 穷尽检查)
sealed class Result {}
class Ok extends Result {}
class Err extends Result {}
// typedef(简化长类型)
typedef JsonMap = Map<String, dynamic>;
// 断言与调试
assert(cond, 'message'); // 仅 debug 生效
debugPrint('log'); // 长日志不截断(本项目用 AppLogger)相关:Flutter 速查 | 返回速查区