Flutter 3 跨平台应用开发:从 Widget 到发布
Flutter 3 跨平台应用开发实战:从 Widget 到发布
环境准备与项目初始化
安装 Flutter SDK
从 Flutter 官网 下载最新稳定版 SDK,解压后将其 bin 目录添加到系统 PATH。在终端执行 flutter doctor 检查环境依赖,根据提示安装缺失的组件(如 Android Studio、Xcode、Chrome 等)。确保所有检查项均为绿色勾选状态。
创建第一个 Flutter 项目
打开终端,执行以下命令创建项目:
flutter create my_first_app
进入项目目录,使用你喜欢的 IDE(推荐 VS Code 或 Android Studio)打开。项目结构如下:
lib/main.dart:应用入口文件,所有 Dart 代码都写在这里或其导入的文件中。pubspec.yaml:配置文件,用于声明项目依赖、资源等。android/和ios/:原生工程目录,多数情况下无需手动修改。
在 main.dart 中,默认模板已经包含了一个简单的计数器应用。我们先运行它来验证环境是否正常。
flutter run
选择一个连接的设备(模拟器或真机),应用将启动并展示一个带浮动按钮的页面。
理解 Widget 体系:一切皆为组件
Widget 的核心概念
Flutter 中所有 UI 元素都是 Widget,从文本、按钮到整个页面。Widget 分为两大类:
- StatelessWidget(无状态组件):UI 静态不变,依赖外部数据一次性构建。
- StatefulWidget(有状态组件):内部持有可变状态,状态变化时触发界面重绘。
入门时重点掌握如何组合和嵌套 Widget,构建出想要的布局。
基础布局 Widget
// 一个简单的个人卡片界面
Scaffold(
appBar: AppBar(title: Text('个人名片')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
radius: 60,
backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
),
SizedBox(height: 16),
Text(
'Flutter 开发者',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('专注移动跨平台技术', style: TextStyle(color: Colors.grey)),
],
),
),
)
以上代码展示了 Scaffold(页面骨架)、Center、Column、SizedBox 等常用布局组件。通过组合这些无状态组件,可以快速搭建静态界面。
引入状态:StatefulWidget
当界面需要响应用户交互或数据变化时,使用 StatefulWidget。以下是一个数字增减的示例:
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.remove),
onPressed: () => setState(() { _count--; }),
),
Text('$_count', style: TextStyle(fontSize: 30)),
IconButton(
icon: Icon(Icons.add),
onPressed: () => setState(() { _count++; }),
),
],
);
}
}
调用 setState() 会通知框架重新执行 build 方法,并仅更新发生变化的部分。
导航与路由管理
基本页面跳转
使用 Navigator 进行页面间的切换。最简单的跳转:
// 跳转到新页面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
// 返回上一页
Navigator.pop(context);
命名路由
对于复杂应用,推荐在 MaterialApp 中定义命名路由表:
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomePage(),
'/details': (context) => DetailPage(),
},
)
页面内使用 Navigator.pushNamed(context, '/details') 跳转。
传递参数
传递简单参数:在路由的 builder 函数中直接接收构造参数。使用命名路由时,可通过 onGenerateRoute 解析参数:
onGenerateRoute: (settings) {
if (settings.name == '/details') {
final args = settings.arguments as Map;
return MaterialPageRoute(
builder: (context) => DetailPage(data: args['data']),
);
}
}
在源页面调用时传入参数:
Navigator.pushNamed(context, '/details', arguments: {'data': someData});
网络请求与数据处理
添加 http 依赖
在 pubspec.yaml 中添加:
dependencies:
http: ^1.1.0
执行 flutter pub get 安装。
发送 GET 请求并解析 JSON
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<List<Post>> fetchPosts() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
List jsonData = jsonDecode(response.body);
return jsonData.map((json) => Post.fromJson(json)).toList();
} else {
throw Exception('Failed to load posts');
}
}
class Post {
final int id;
final String title;
final String body;
Post({required this.id, required this.title, required this.body});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
界面展示异步数据
使用 FutureBuilder 优雅处理异步数据:
FutureBuilder<List<Post>>(
future: fetchPosts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) => ListTile(
title: Text(snapshot.data![index].title),
subtitle: Text(snapshot.data![index].body),
),
);
}
},
)
状态管理入门:Provider 模式
安装 Provider
pubspec.yaml 中添加:
dependencies:
provider: ^6.1.1
创建数据模型与 ChangeNotifier
import 'package:flutter/material.dart';
class CartModel extends ChangeNotifier {
List<String> _items = [];
List<String> get items => _items;
void add(String item) {
_items.add(item);
notifyListeners();
}
void remove(int index) {
_items.removeAt(index);
notifyListeners();
}
}
在顶层注入并消费
在 main.dart 中使用 ChangeNotifierProvider 包裹 MaterialApp:
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CartModel(),
child: MyApp(),
),
);
}
在任意后代 Widget 中读取和操作状态:
// 读取
final cart = context.watch<CartModel>();
// 触发方法
context.read<CartModel>().add('商品A');
本地数据持久化:SharedPreferences 与 SQLite
使用 SharedPreferences 存储键值对
依赖:
dependencies:
shared_preferences: ^2.2.2
保存与读取:
final prefs = await SharedPreferences.getInstance();
// 保存
await prefs.setString('username', 'FlutterDev');
// 读取
String? username = prefs.getString('username');
适用于简单配置、用户偏好等。
使用 sqflite 管理结构化数据
依赖:
dependencies:
sqflite: ^2.3.0
path: ^1.8.3
初始化数据库并创建表:
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
Future<Database> openDatabase() async {
final dbPath = await getDatabasesPath();
return openDatabase(
join(dbPath, 'app.db'),
onCreate: (db, version) {
return db.execute(
'CREATE TABLE notes(id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT)',
);
},
version: 1,
);
}
插入、查询、删除等操作使用 insert、query、delete 方法,与原生 SQLite 类似。
界面美化与适配
主题定制
在 MaterialApp 中设置全局主题:
MaterialApp(
theme: ThemeData(
primarySwatch: Colors.indigo,
visualDensity: VisualDensity.adaptivePlatformDensity,
textTheme: TextTheme(
headline6: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
)
单个界面也可以通过 Theme.of(context) 动态获取主题色,保持风格一致。
响应式布局
使用 MediaQuery 获取屏幕尺寸,或借助 LayoutBuilder 按父级约束调整布局。例如,平板采用左右分栏,手机使用竖排:
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return Row(children: [Expanded(child: leftPanel), Expanded(child: rightPanel)]);
} else {
return Column(children: [leftPanel, rightPanel]);
}
},
)
构建与发布
生成 Android APK / App Bundle
在终端执行:
flutter build apk --release
APK 文件位于 build/app/outputs/flutter-apk/app-release.apk。
如需上传到 Google Play,生成 App Bundle:
flutter build appbundle --release
构建 iOS 应用
需要 macOS 环境和 Xcode。打开 ios/Runner.xcworkspace,在 Xcode 中配置签名团队,然后执行:
flutter build ipa --export-method app-store
生成的 .ipa 文件可通过 Transporter 或命令行上传到 App Store Connect。
应用图标与启动页
替换图标可使用 flutter_launcher_icons 包。在 pubspec.yaml 中配置后运行命令即可自动生成各尺寸图标。
启动页(闪屏页)可在原生工程中修改,或使用 flutter_native_splash 包快速定制。
版本管理与更新
在 pubspec.yaml 中修改 version 字段,例如 version: 1.0.1+2,其中 1.0.1 是版本名,+2 是版本号(数字递增)。打包时此信息会嵌入应用。
学习路径建议
- 基础:彻底掌握 Dart 语言基础(变量、函数、异步、类)。
- 界面:熟练使用 Material 组件、布局系统、列表。
- 交互:学习表单、手势、动画。
- 架构:理解状态管理方案(Provider 后可选 Riverpod、Bloc)。
- 工程化:掌握网络、存储、路由、国际化。
- 发布:测试、性能优化、打包上线。
跟随本教程,从零搭建一个完整应用并发布到应用商店,是巩固技能的最佳方式。立即动手,开启你的 Flutter 跨平台开发之旅吧!