外观
环境搭建与 Dart 准备
先确定目标平台
先选一个平台跑通,再补其他平台的工具链。Flutter SDK 内包含配套 Dart SDK,通常无需另装一套 Dart。
| 目标 | 需要准备 | 首次验收 |
|---|---|---|
| Android | Android SDK、兼容的 JDK、模拟器或开启调试的真机 | flutter devices 能列出设备 |
| iOS | macOS、Xcode、模拟器或已配置签名的真机 | 在 Xcode 完成必要组件配置后启动应用 |
| Web | 支持的浏览器与 Flutter Web 工具链 | 能在浏览器看到首页 |
| 桌面 | 对应操作系统的原生构建工具 | 对目标平台执行 flutter run |
按 官方安装指南 安装 SDK 并配置 PATH,然后检查:
sh
flutter --version
dart --version
flutter doctor -v
flutter devicesdoctor 中未使用平台的提示不一定影响当前开发。优先解决目标平台的错误;Android 许可问题可按提示运行 flutter doctor --android-licenses。iOS 的原生依赖配置取决于插件与 SDK 版本,按当前安装指南处理。
创建与运行项目
sh
flutter create notes_app
cd notes_app
flutter pub get
flutter run多个设备同时可用时,用 flutter run -d <device-id> 指定目标;Web 可用 flutter run -d chrome。这里的占位符要替换为实际设备 ID。
| 文件或目录 | 职责 |
|---|---|
lib/main.dart | Dart 入口与根组件 |
pubspec.yaml | SDK 约束、依赖、资源与版本号 |
pubspec.lock | 锁定依赖解析结果,应用项目应提交 |
test/ | 单元测试与 Widget 测试 |
android/、ios/、web/ 等 | 原生宿主、权限、签名和平台配置 |
将 lib/main.dart 替换为下面的独立示例:
dart
import 'package:flutter/material.dart';
void main() => runApp(const NotesApp());
class NotesApp extends StatelessWidget {
const NotesApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '个人笔记',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(title: const Text('个人笔记')),
body: const SafeArea(
child: Center(child: Text('第一条 Flutter 笔记')),
),
),
);
}
}热重载通常保留当前状态,适合观察 UI 修改;热重启会重新执行 Dart 应用入口。修改原生代码或部分平台配置后,需要停止并重新构建。两者都不能代替一次完整的冷启动验证。
Dart 必备概念
| 概念 | 需要掌握的用法 |
|---|---|
| 空安全 | String 与 String?;优先判断空值或使用 ??,避免随意添加 ! |
| 变量 | final 表示只能赋值一次,const 表示编译期常量;final 集合仍可修改内容 |
| 集合 | List、Map、Set,以及 map、where、展开运算符 |
| 构造函数 | 命名参数、required、不可变字段、const 构造函数 |
| 函数 | 闭包、回调、返回值与命名参数 |
| 异步 | Future 表示一次异步结果,Stream 表示一系列异步事件 |
下面的代码可单独保存为 Dart 文件,用 dart run 文件名.dart 观察结果:
dart
Future<List<String>> searchNotes(String? input) async {
final keyword = (input ?? '').trim().toLowerCase();
await Future<void>.delayed(const Duration(milliseconds: 200));
const titles = ['Flutter 布局', 'Dart 空安全', 'Flutter 状态'];
return titles
.where((title) => title.toLowerCase().contains(keyword))
.toList();
}
Future<void> main() async {
try {
final notes = await searchNotes('flutter');
print(notes); // [Flutter 布局, Flutter 状态]
} catch (error) {
print('搜索失败:$error');
}
}async 和 await 用于组织异步执行,并不会自动把 CPU 密集计算移到后台。原生平台的重计算可评估 isolate;Web 的并行方案要单独验证。参见 Dart 异步 与 isolate 文档。
验证与下一步
确认首页可见,修改文字后热重载生效,停止应用后可以再次启动。替换生成的默认计数器页面后,也要同步修改 test/widget_test.dart 中原有的计数器断言。
接下来阅读 页面、控件与布局,把首屏扩展成可滚动的笔记列表。