第11章 Flutter跨平台开发基础¶
学习目标:掌握Flutter跨平台开发框架,理解Dart语言特性,能够使用Flutter构建iOS和Android双平台应用。
预计学习时间:7-10天 实践时间:3-4天
目录¶
1. Flutter概述与优势¶
1.1 什么是Flutter¶
Flutter是Google推出的开源UI框架,使用Dart语言,一套代码可同时构建iOS、Android、Web、桌面应用。
1.2 Flutter vs 原生Android¶
| 特性 | Flutter | 原生Android |
|---|---|---|
| 开发语言 | Dart | Kotlin/Java |
| UI渲染 | Skia自绘引擎 | 平台原生渲染 |
| 性能 | 接近原生 | 原生 |
| 代码复用 | 90%+ | 仅Android |
| 包大小 | 较大(包含引擎) | 较小 |
| 生态 | 快速增长 | 成熟丰富 |
1.3 适用场景¶
推荐使用Flutter的场景: - ✅ 需要快速开发双平台应用 - ✅ UI复杂且需要高度自定义 - ✅ 团队规模较小,资源有限 - ✅ 原型验证和MVP开发
推荐使用原生的场景: - ✅ 需要深度集成平台特性 - ✅ 对包大小敏感 - ✅ 已有成熟的原生团队 - ✅ 需要复杂的后台任务
2. Dart语言基础¶
2.1 Dart概述¶
Dart是Google开发的面向对象编程语言,语法类似JavaScript和Java的混合。
2.2 基础语法¶
// 变量声明
var name = 'Flutter'; // 类型推断
String framework = 'Flutter'; // 显式类型
final version = 3.0; // 运行时常量
const pi = 3.14159; // 编译期常量
// 空安全(Null Safety)
String? nullableName; // 可为null
String nonNullName = 'Flutter'; // 不可为null
// 函数定义
int add(int a, int b) {
return a + b;
}
// 箭头函数
int multiply(int a, int b) => a * b;
// 可选参数
void greet(String name, {String greeting = 'Hello'}) {
print('$greeting, $name!');
}
// 使用
greet('Flutter'); // Hello, Flutter!
greet('Dart', greeting: 'Hi'); // Hi, Dart!
2.3 面向对象¶
// 类定义
class Person {
// 属性
String name;
int age;
// 构造函数
Person(this.name, this.age);
// 命名构造函数
Person.guest() : name = 'Guest', age = 0;
// 方法
void introduce() {
print('I am $name, $age years old');
}
// Getter/Setter
String get info => '$name, $age';
set info(String value) {
var parts = value.split(',');
name = parts[0].trim();
age = int.parse(parts[1].trim());
}
}
// 继承
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
@override
void introduce() {
super.introduce();
print('I study at $school');
}
}
// Mixin
mixin Logger {
void log(String message) {
print('[LOG] $message');
}
}
class Service with Logger {
void doSomething() {
log('Doing something');
}
}
2.4 异步编程¶
// Future - 异步操作
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return 'Data loaded';
}
// 使用
void main() async {
print('Loading...');
var data = await fetchData();
print(data);
}
// Stream - 数据流
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
// 监听Stream
void listenToStream() {
countStream(5).listen(
(data) => print('Received: $data'),
onDone: () => print('Stream completed'),
);
}
3. Flutter环境搭建¶
3.1 安装Flutter SDK¶
# Windows
# 1. 下载Flutter SDK
# https://docs.flutter.dev/get-started/install/windows
# 2. 解压到 C:\flutter
# 3. 配置环境变量
setx PATH "%PATH%;C:\flutter\bin"
# 4. 验证安装
flutter doctor
# macOS
# 使用Homebrew安装
brew install flutter
# 或手动安装
# 1. 下载SDK
# 2. 解压到 ~/flutter
# 3. 添加到PATH
echo 'export PATH="$PATH:$HOME/flutter/bin"' >> ~/.zshrc
source ~/.zshrc
3.2 配置VS Code¶
# 安装Flutter扩展
code --install-extension Dart-Code.flutter
code --install-extension Dart-Code.dart
3.3 创建第一个Flutter项目¶
# 创建项目
flutter create my_first_app
cd my_first_app
# 运行应用
flutter run
# 指定设备
flutter devices
flutter run -d emulator-5554
3.4 项目结构¶
my_first_app/
├── android/ # Android原生代码
├── ios/ # iOS原生代码
├── lib/ # Dart代码(主要开发目录)
│ └── main.dart # 应用入口
├── test/ # 测试代码
├── pubspec.yaml # 依赖配置
└── pubspec.lock # 依赖锁定
4. Widget基础¶
4.1 Widget概述¶
Flutter中一切皆Widget。Widget是UI的描述,不可变,通过重建实现UI更新。
4.2 StatelessWidget¶
// 无状态Widget
class HelloWidget extends StatelessWidget {
final String name;
const HelloWidget({Key? key, required this.name}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
'Hello, $name!',
style: TextStyle(fontSize: 24),
);
}
}
4.3 StatefulWidget¶
// 有状态Widget
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $_count'),
ElevatedButton(
onPressed: _increment,
child: Text('Increment'),
),
],
);
}
}
4.4 常用基础Widget¶
// 文本
Text(
'Hello Flutter',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
)
// 图片
Image.network('https://example.com/image.png')
Image.asset('assets/images/logo.png')
// 图标
Icon(Icons.home)
Icon(Icons.favorite, color: Colors.red, size: 32)
// 按钮
ElevatedButton(
onPressed: () {},
child: Text('Click Me'),
)
TextButton(
onPressed: () {},
child: Text('Text Button'),
)
OutlinedButton(
onPressed: () {},
child: Text('Outlined Button'),
)
IconButton(
onPressed: () {},
icon: Icon(Icons.add),
)
// 输入框
TextField(
decoration: InputDecoration(
labelText: 'Username',
hintText: 'Enter your username',
prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
),
onChanged: (value) {
print('Input: $value');
},
)
5. 布局系统¶
5.1 基础布局Widget¶
// Container - 容器
Container(
width: 200,
height: 100,
padding: EdgeInsets.all(16),
margin: EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 4,
offset: Offset(2, 2),
),
],
),
child: Text('Container'),
)
// Row - 水平排列
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.home),
Icon(Icons.search),
Icon(Icons.person),
],
)
// Column - 垂直排列
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Title', style: TextStyle(fontSize: 24)),
Text('Subtitle', style: TextStyle(fontSize: 16)),
SizedBox(height: 16),
ElevatedButton(onPressed: () {}, child: Text('Action')),
],
)
// Stack - 层叠
Stack(
children: [
Image.network('https://example.com/bg.jpg'),
Positioned(
bottom: 16,
left: 16,
child: Text(
'Overlay Text',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
],
)
5.2 滚动布局¶
// ListView - 列表
ListView(
children: [
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
],
)
// 动态列表
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index].title),
subtitle: Text(items[index].subtitle),
);
},
)
// GridView - 网格
GridView.count(
crossAxisCount: 2,
children: List.generate(20, (index) {
return Card(
child: Center(child: Text('Item $index')),
);
}),
)
// 分页加载
ListView.builder(
controller: _scrollController,
itemCount: items.length + 1,
itemBuilder: (context, index) {
if (index == items.length) {
return _isLoading ? CircularProgressIndicator() : SizedBox();
}
return ListTile(title: Text(items[index]));
},
)
5.3 响应式布局¶
// MediaQuery获取屏幕信息
var screenSize = MediaQuery.of(context).size;
var isPortrait = screenSize.height > screenSize.width;
// LayoutBuilder响应式
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return WideLayout();
} else {
return NarrowLayout();
}
},
)
// OrientationBuilder方向变化
OrientationBuilder(
builder: (context, orientation) {
return GridView.count(
crossAxisCount: orientation == Orientation.portrait ? 2 : 4,
children: [...],
);
},
)
6. 事件处理¶
6.1 点击事件¶
// GestureDetector - 手势检测
GestureDetector(
onTap: () => print('Tapped'),
onDoubleTap: () => print('Double tapped'),
onLongPress: () => print('Long pressed'),
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
)
// InkWell - 水波纹效果
InkWell(
onTap: () {},
child: Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Clickable Card'),
),
),
)
6.2 表单处理¶
class LoginForm extends StatefulWidget {
@override
_LoginFormState createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final _formKey = GlobalKey<FormState>();
String _email = '';
String _password = '';
void _submit() {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
print('Email: $_email, Password: $_password');
}
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter email';
}
return null;
},
onSaved: (value) => _email = value!,
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || value.length < 6) {
return 'Password must be at least 6 characters';
}
return null;
},
onSaved: (value) => _password = value!,
),
ElevatedButton(
onPressed: _submit,
child: Text('Login'),
),
],
),
);
}
}
7. Flutter 3.27/3.29新特性¶
7.1 Flutter版本演进¶
Flutter在2024-2025年持续快速发展,主要版本发布节奏:
| 版本 | 发布时间 | 主要特性 |
|---|---|---|
| Flutter 3.24 | 2024年8月 | 稳定版改进 |
| Flutter 3.27 | 2024年12月 | Impeller改进、性能优化 |
| Flutter 3.29 | 2025年2月 | iOS全Impeller迁移、开发工具优化 |
| Flutter 3.32 | 2025年5月 | 更多平台支持 |
7.2 Impeller渲染引擎¶
Impeller是Flutter的新一代渲染引擎,从Flutter 3.29开始iOS平台完全迁移到Impeller:
Impeller优势¶
- 更少的卡顿:预编译着色器,消除运行时着色器编译导致的卡顿
- 更好的可预测性:更一致的帧率和性能表现
- 更低的内存占用:优化的内存使用模式
- 更好的可调试性:改进的调试工具和性能分析
iOS全Impeller迁移¶
从Flutter 3.29开始,iOS完全删除Skia支持:
// 之前可以通过以下方式禁用Impeller(3.29后不再有效)
// <key>FLTEnableImpeller</key>
// <false/>
// 现在iOS强制使用Impeller
Android Impeller状态¶
Android平台Impeller仍在积极开发中:
// 在Android上启用Impeller(实验性)
// android/app/src/main/AndroidManifest.xml
<manifest>
<application
android:enableImpeller="true">
</application>
</manifest>
7.3 开发工具优化¶
热重载改进¶
Flutter 3.27+显著改进了热重载性能:
DevTools增强¶
- 性能视图改进:更清晰的帧时间线
- 内存分析器:更好的内存泄漏检测
- 网络分析器:HTTP请求详细分析
- Widget检查器:更直观的Widget树查看
7.4 Material 3更新¶
Flutter 3.27+更新了Material 3组件:
// 使用Material 3主题
MaterialApp(
theme: ThemeData(
useMaterial3: true, // 启用Material 3
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
),
),
home: MyHomePage(),
)
// 新的Material 3组件
NavigationBar( // 替代BottomNavigationBar
destinations: [
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
],
selectedIndex: _selectedIndex,
onDestinationSelected: (index) {
setState(() => _selectedIndex = index);
},
)
// 新的按钮样式
FilledButton(onPressed: () {}, child: Text('Filled'))
FilledButton.tonal(onPressed: () {}, child: Text('Tonal'))
OutlinedButton(onPressed: () {}, child: Text('Outlined'))
TextButton(onPressed: () {}, child: Text('Text'))
7.5 Dart 3新特性¶
Flutter 3.27+配套Dart 3,带来语言级改进:
// 记录类型(Records)
var record = ('first', a: 2, b: true, 'last');
print(record.$1); // 访问位置字段: 'first'
print(record.a); // 访问命名字段: 2
// 模式匹配(Patterns)
var (a, b) = ('left', 'right');
switch (value) {
case (var x, var y) when x > y:
print('First is greater');
case (var x, var y) when x == y:
print('Equal');
default:
print('Second is greater');
}
// 类修饰符
sealed class Animal {}
final class Dog extends Animal {}
interface class Canine {}
mixin class Walker {}
7.6 升级指南¶
从旧版本升级到Flutter 3.27+:
# 检查当前版本
flutter --version
# 升级到最新稳定版
flutter upgrade
# 更新依赖
flutter pub upgrade
# 检查破坏性变更
flutter pub outdated
# 运行迁移工具
flutter fix --apply
常见迁移问题¶
- iOS构建问题:确保Xcode版本≥15
- Android构建问题:更新Gradle到8.0+
- 依赖兼容性:检查第三方包是否支持新版本
8. 实践练习¶
练习1:Flutter环境搭建¶
任务:完成Flutter开发环境配置
要求: 1. 安装Flutter SDK 2. 配置VS Code 3. 创建并运行第一个Flutter应用 4. 截图验证
练习2:登录界面¶
任务:使用Flutter实现登录界面
要求: - 邮箱和密码输入框 - 表单验证 - 登录按钮 - 响应式布局
练习3:商品列表¶
任务:实现商品展示列表
要求: - 使用ListView.builder - 图片+标题+价格布局 - 点击跳转到详情 - 支持下拉刷新
本章小结¶
核心要点¶
- Flutter使用Dart语言,一套代码构建多平台应用
- Dart语法类似JavaScript+Java,支持空安全和异步编程
- Widget是Flutter的核心,分为Stateless和Stateful
- 布局系统包括Row、Column、Stack、ListView等
- 事件处理使用GestureDetector和Form
下一步¶
完成本章学习后,请进入第12章:Flutter状态管理与路由。
本章完成时间:预计7-10天