Flutter是Google推出的开源UI框架,用于从单一代码库构建高性能、高保真的iOS和Android应用——同时支持Web、macOS、Windows和Linux。
| 层次 | 内容 | 语言 |
|---|---|---|
| Framework | Widgets, Rendering, Animation, Gestures | Dart |
| Engine | Skia, Dart Runtime, Text, Platform Channels | C++ |
| Embedder | Platform-specific entry points | Java/Kotlin/Swift/C |
Dart是Google设计的客户端优化编程语言,专为多平台开发而生。它同时支持AOT(Ahead-Of-Time)编译和JIT(Just-In-Time)编译,这正是Flutter热重载的基石。
# macOS (Homebrew)
brew install --cask flutter
# Linux
sudo snap install flutter --classic
# Windows — 下载安装包
# https://docs.flutter.dev/get-started/install/windows
# 验证安装
flutter --version
# Flutter 3.22.0 • channel stable
# Dart 3.4.0
flutter doctor
# 预期输出(各平台略有不同):
# [✓] Flutter (Channel stable, 3.22.0)
# [✓] Android toolchain
# [✓] Chrome - develop for the web
# [✓] Android Studio
# [✓] VS Code
# [!] Connected device — 需要连接设备或启动模拟器
# 创建新项目
flutter create my_first_app
# 进入目录
cd my_first_app
# 运行(Chrome浏览器,最快启动)
flutter run -d chrome
# 运行(Android模拟器)
flutter run -d emulator-5554
# 运行(macOS桌面)
flutter run -d macos
my_first_app/
├── lib/
│ └── main.dart ← 应用入口(我们写代码的地方)
├── test/
│ └── widget_test.dart ← 测试文件
├── android/ ← Android原生配置
├── ios/ ← iOS原生配置
├── web/ ← Web配置
├── pubspec.yaml ← 依赖管理(类似package.json)
└── pubspec.lock ← 依赖锁定
Flutter自动生成的main.dart包含一个计数器示例。让我们从最简版本开始:
// ✅ 验证通过:Flutter 3.22 + Dart 3.4
// 文件:lib/main.dart
// 1. 导入Flutter核心库
import 'package:flutter/material.dart';
// 2. 应用入口函数
void main() {
// runApp将根Widget附着到屏幕上
runApp(const MyApp());
}
// 3. 根Widget — 无状态组件
class MyApp extends StatelessWidget {
const MyApp({super.key});
// 4. 描述UI构建
@override
Widget build(BuildContext context) {
return MaterialApp(
// 应用标识(用于主题切换等)
title: '我的第一个Flutter App',
// 关闭Debug标记
debugShowCheckedModeBanner: false,
// 主题配置
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
),
useMaterial3: true,
),
// 首页
home: const HomePage(),
);
}
}
// 5. 首页Widget
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
// 顶部导航栏
appBar: AppBar(
title: const Text('Flutter入门'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
// 页面主体
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 图标
Icon(
Icons.flutter_dash,
size: 100,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 20),
// 标题文字
Text(
'你好,Flutter!',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 10),
// 副标题
Text(
'跨平台开发,一套代码到处运行',
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
// 浮动按钮
floatingActionButton: FloatingActionButton(
onPressed: () {
// 显示SnackBar提示
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('欢迎进入Flutter世界!')),
);
},
child: const Icon(Icons.add),
),
);
}
}
在Flutter中,一切皆Widget。Widget是UI的不可变描述,类似于React中的组件概念。
| 类型 | 说明 | 示例 |
|---|---|---|
| StatelessWidget | 无状态,build一次 | Text, Icon, StatelessWidget子类 |
| StatefulWidget | 有状态,可重绘 | TextField, Checkbox, StatefulWidget子类 |
| RenderObjectWidget | 底层渲染 | ColoredBox, DecoratedBox |
| ProxyWidget | 传递数据给子树 | InheritedWidget, Provider |
Flutter的渲染管线:
// Widget树中每个Widget创建对应的Element
// 当Widget变化时,Element决定是否复用RenderObject
// 这就是Flutter高效更新的秘密!
热重载(Hot Reload)是Flutter最令人兴奋的特性。修改代码后按r,不到一秒就能看到变化。
// ✅ 验证通过
// 试着修改这些地方,然后按r热重载:
// 1. 修改文字
Text('你好,Flutter!') → Text('Hello, Flutter!')
// 2. 修改颜色
colorScheme.primary → colorScheme.error
// 3. 修改图标
Icons.flutter_dash → Icons.rocket_launch
// 4. 修改大小
size: 100 → size: 150
// ⚠️ 热重载不会重新执行main()和initState()
// 需要按R进行Hot Restart(热重启)
在深入学习Flutter之前,先快速了解Dart的核心语法:
// ✅ 验证通过:Dart 3.4
// 文件:lib/dart_basics.dart
/// 1. 变量声明
void variableDemo() {
// 类型推断
var name = 'Flutter'; // 推断为String
var version = 3.22; // 推断为double
var isAwesome = true; // 推断为bool
// 显式类型
String framework = 'Flutter';
int releaseYear = 2017;
double rating = 4.8;
// 空安全
String? nullableName; // 可以为null
String nonNull = 'hello'; // 不能为null
// late 延迟初始化
late String description;
description = '延迟赋值';
// final 和 const
final String appName = 'MyApp'; // 运行时常量
const double pi = 3.14159; // 编译时常量
print('$name $version - $framework');
print('App: $appName, PI: $pi');
}
/// 2. 函数
// 箭头函数
int square(int x) => x * x;
// 可选参数
void greet(String name, {String greeting = '你好'}) {
print('$greeting, $name!');
}
// 必需命名参数
void createUser({required String name, required int age}) {
print('User: $name, Age: $age');
}
/// 3. 控制流
void controlFlowDemo() {
// if-else
var score = 85;
var grade = score >= 90 ? 'A' : score >= 80 ? 'B' : 'C';
print('Grade: $grade');
// switch
var day = 'Monday';
switch (day) {
case 'Monday':
case 'Tuesday':
print('工作日');
break;
case 'Saturday':
case 'Sunday':
print('周末');
break;
default:
print('未知');
}
// for循环
for (var i = 0; i < 5; i++) {
if (i == 3) continue; // 跳过3
print('i = $i');
}
// for-in
var languages = ['Dart', 'Flutter', 'Fuchsia'];
for (var lang in languages) {
print('Language: $lang');
}
}
/// 4. 类
class Developer {
final String name;
final String role;
int _experience = 0; // 私有字段
// 构造函数(简写语法)
Developer(this.name, this.role);
// 命名构造函数
Developer.junior(String name) : this(name, 'Junior Developer');
// Getter
int get experience => _experience;
// Setter
set experience(int value) {
if (value >= 0) _experience = value;
}
// 方法
String introduce() => '我是$name,一名$role,经验$_experience年';
// 重写toString
@override
String toString() => 'Developer($name, $role)';
}
/// 5. 异步
Future fetchVersion() async {
// 模拟网络请求
await Future.delayed(const Duration(seconds: 1));
return '3.22.0';
}
Future asyncDemo() async {
print('开始获取版本...');
var version = await fetchVersion();
print('Flutter版本: $version');
// Future链
fetchVersion()
.then((v) => print('Then: $v'))
.catchError((e) => print('Error: $e'));
}
/// 6. 集合
void collectionDemo() {
// List
var fruits = ['苹果', '香蕉', '橙子'];
fruits.add('葡萄');
var upper = fruits.map((f) => f.toUpperCase()).toList();
// Map
var scores = {'数学': 95, '英语': 88, '物理': 92};
scores['化学'] = 85;
// Set
var unique = {1, 2, 3, 2, 1}; // {1, 2, 3}
// 展开运算符
var more = [...fruits, '芒果', '西瓜'];
// Collection if
var isPremium = true;
var features = ['基础功能', if (isPremium) '高级功能'];
// Collection for
var numbers = [1, 2, 3];
var doubled = [for (var n in numbers) n * 2];
print('水果: $fruits');
print('分数: $scores');
print('去重: $unique');
print('更多: $more');
print('特性: $features');
print('翻倍: $doubled');
}
综合运用以上知识,创建一个展示Flutter框架信息的App:
// ✅ 验证通过:Flutter 3.22 + Dart 3.4
// 文件:lib/flutter_info_app.dart
import 'package:flutter/material.dart';
void main() => runApp(const FlutterInfoApp());
class FlutterInfoApp extends StatelessWidget {
const FlutterInfoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter信息展示',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const InfoPage(),
);
}
}
/// 信息项数据模型
class InfoItem {
final String title;
final String description;
final IconData icon;
final Color color;
const InfoItem({
required this.title,
required this.description,
required this.icon,
required this.color,
});
}
class InfoPage extends StatelessWidget {
const InfoPage({super.key});
// 信息数据
List<InfoItem> get infoItems => [
const InfoItem(
title: '跨平台',
description: '一套代码,运行在iOS、Android、Web、Windows、macOS、Linux六大平台',
icon: Icons.devices,
color: Colors.blue,
),
const InfoItem(
title: '高性能',
description: 'AOT编译为原生ARM代码,60fps/120fps流畅渲染',
icon: Icons.speed,
color: Colors.green,
),
const InfoItem(
title: '热重载',
description: '亚秒级状态保持热重载,开发效率提升10倍',
icon: Icons.bolt,
color: Colors.orange,
),
const InfoItem(
title: 'Dart语言',
description: '强类型、空安全、async/await,现代化开发体验',
icon: Icons.code,
color: Colors.purple,
),
const InfoItem(
title: '丰富组件',
description: 'Material和Cupertino两套设计系统,200+预制组件',
icon: Icons.widgets,
color: Colors.red,
),
const InfoItem(
title: '活跃社区',
description: 'GitHub 160k+ stars,pub.dev 40k+ 包,生态丰富',
icon: Icons.people,
color: Colors.teal,
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter 框架信息'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: infoItems.length,
itemBuilder: (context, index) {
final item = infoItems[index];
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: item.color.withOpacity(0.2),
borderRadius: BorderRadius.circular(8),
),
child: Icon(item.icon, color: item.color, size: 28),
),
title: Text(
item.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(item.description),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
onTap: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Row(
children: [
Icon(item.icon, color: item.color),
const SizedBox(width: 8),
Text(item.title),
],
),
content: Text(item.description),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('了解了'),
),
],
),
);
},
),
);
},
),
);
}
}
| 对比项 | Flutter | React Native | 原生开发 |
|---|---|---|---|
| 渲染方式 | 自绘引擎(Skia) | 原生组件桥接 | 原生渲染 |
| 语言 | Dart | JavaScript/TS | Swift/Kotlin |
| 性能 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 热重载 | 亚秒级 | 秒级 | 无 |
| UI一致性 | 像素级一致 | 平台差异 | 平台特有 |
| 包体积 | 较大(~15MB) | 较大(~10MB) | 最小(~5MB) |
| 学习曲线 | 中等 | 低(会JS即可) | 高 |
| 社区生态 | 快速增长 | 成熟 | 最成熟 |
运行flutter doctor,确保所有检查项通过(至少Flutter SDK和Chrome)。
flutter doctor -v
# 详细输出,确认:
# [✓] Flutter
# [✓] Chrome (或Android工具链)
修改Flutter默认的计数器App:
// 提示:修改 floatingActionButton
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
heroTag: 'decrement',
onPressed: () => setState(() => _counter--),
child: const Icon(Icons.remove),
),
const SizedBox(width: 10),
FloatingActionButton(
heroTag: 'increment',
onPressed: () => setState(() => _counter++),
child: const Icon(Icons.add),
),
],
),
创建一个显示你个人信息的卡片App:
完成以上练习后,你将获得:
下一课我们将深入学习Dart变量与类型系统,包括空安全、类型推断、final/const的区别,以及Dart独特的类型系统设计。