🚀 Flutter 从基础学习到项目实战完整教程
适合人群:前端开发工程师、Vue / React 开发者、想学习 Android / iOS App 跨平台开发的新手。
内容定位:从 Dart 基础、Flutter 组件、布局、路由、网络请求、状态管理、本地存储、登录权限、项目架构,到 Android / iOS 打包发布,帮助你真正把 Flutter 用到项目里。
整理时间:2026 年 6 月
📚 目录
- [一、Flutter 是什么?](#一、Flutter 是什么?)
- [二、Flutter 适合做什么?](#二、Flutter 适合做什么?)
- [三、Flutter、React Native、uni-app 对比](#三、Flutter、React Native、uni-app 对比)
- [四、学习 Flutter 前需要掌握什么?](#四、学习 Flutter 前需要掌握什么?)
- [五、Flutter 开发环境搭建](#五、Flutter 开发环境搭建)
- [六、Flutter 常用命令](#六、Flutter 常用命令)
- [七、Flutter 项目目录结构](#七、Flutter 项目目录结构)
- [八、Dart 基础语法](#八、Dart 基础语法)
- [九、Flutter 核心思想:万物皆 Widget](#九、Flutter 核心思想:万物皆 Widget)
- [十、Flutter 常用基础组件](#十、Flutter 常用基础组件)
- [十一、Flutter 布局系统](#十一、Flutter 布局系统)
- [十二、Flutter 页面路由和跳转](#十二、Flutter 页面路由和跳转)
- [十三、Flutter 网络请求](#十三、Flutter 网络请求)
- [十四、JSON 模型转换](#十四、JSON 模型转换)
- 十五、状态管理
- 十六、本地存储
- [十七、登录注册与 Token 拦截](#十七、登录注册与 Token 拦截)
- 十八、权限、图片上传、WebView、地图和推送
- [十九、企业级 Flutter 项目架构](#十九、企业级 Flutter 项目架构)
- [二十、完整项目实战:医疗咨询预约 App](#二十、完整项目实战:医疗咨询预约 App)
- [二十一、Flutter 屏幕适配](#二十一、Flutter 屏幕适配)
- [二十二、Flutter 动画](#二十二、Flutter 动画)
- [二十三、Flutter 性能优化](#二十三、Flutter 性能优化)
- [二十四、Flutter Android 打包发布流程](#二十四、Flutter Android 打包发布流程)
- [二十五、Flutter iOS 打包发布流程](#二十五、Flutter iOS 打包发布流程)
- [二十六、Flutter 常见报错与解决方案](#二十六、Flutter 常见报错与解决方案)
- [二十七、Flutter 学习路线](#二十七、Flutter 学习路线)
- [二十八、Flutter 练手项目推荐](#二十八、Flutter 练手项目推荐)
- [二十九、Flutter 面试常考题](#二十九、Flutter 面试常考题)
- [三十、Flutter 资源与文档汇总](#三十、Flutter 资源与文档汇总)
一、Flutter 是什么?
Flutter 是 Google 推出的开源跨平台 UI 框架,使用 Dart 语言开发。它最大的特点是:一套代码可以构建 Android、iOS、Web、Windows、macOS、Linux 等多平台应用。
你可以把 Flutter 理解成:
Flutter = Dart 语言 + Widget 组件系统 + 跨平台渲染引擎 + App 工程化能力。
对于前端开发来说,Flutter 和 Vue / React 有很多相似点:
| 前端概念 | Flutter 对应概念 |
|---|---|
| 组件 Component | Widget |
| props | 构造参数 |
| state | State / Provider / Riverpod |
| router | Navigator / go_router |
| axios | dio / http |
| localStorage | shared_preferences / secure storage |
| CSS Flex | Row / Column / Expanded |
| 页面 Page | Screen / Route |
所以,如果你已经会 Vue、React、JavaScript、CSS,再学 Flutter 会更容易上手。难点主要在于 Dart 语法、移动端打包、证书签名、原生权限和 App 工程化。
二、Flutter 适合做什么?
✅ 非常适合的场景
| 场景 | 说明 |
|---|---|
| 📱 Android / iOS App | 一套代码开发双端,节省开发成本 |
| 🏥 医疗咨询 App | 表单、预约、图片上传、在线咨询、用户中心都适合 |
| 🛒 商城 App | 商品列表、购物车、订单、支付、个人中心 |
| 📰 新闻资讯 App | 首页、分类、列表、详情、收藏、搜索 |
| 🎓 在线课程 App | 视频播放、课程目录、用户登录、学习记录 |
| 📊 企业后台移动端 | 数据看板、审批、CRM、OA、工单系统 |
| 🧾 记账 / 工具类 App | 本地存储、图表、提醒、轻量业务 |
⚠️ 不一定优先选择的场景
| 场景 | 原因 |
|---|---|
| SEO 要求很高的网站 | Flutter Web 首屏和 SEO 不如传统 HTML / SSR 方案 |
| 微信小程序 | Flutter 不能直接变成微信小程序,建议用原生小程序、uni-app、Taro |
| 极重原生能力项目 | 如果大量依赖系统底层能力,原生 Android / iOS 仍然更稳 |
三、Flutter、React Native、uni-app 对比
| 对比项 | Flutter | React Native | uni-app |
|---|---|---|---|
| 开发语言 | Dart | JavaScript / TypeScript | Vue 语法 |
| 渲染方式 | 自绘 UI | 调用原生组件 | 多端编译适配 |
| UI 一致性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 性能表现 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 前端上手难度 | 中等 | 较低 | 很低 |
| App 体验 | 很好 | 较好 | 一般到较好 |
| 小程序支持 | 弱 | 弱 | 强 |
| 生态资源 | pub.dev | npm | DCloud 插件市场 |
| 适合人群 | 想深入 App 跨平台开发 | React 团队 | Vue / 小程序团队 |
怎么选?
- 如果你主要做 Android / iOS App,并且希望 UI 一致、性能稳定:优先 Flutter。
- 如果团队本来就是 React 技术栈:可以考虑 React Native。
- 如果主要目标是 微信小程序 + H5 + App:uni-app 更顺手。
- 如果你想提升个人技术竞争力,Flutter 是很值得学的跨平台方向。
四、学习 Flutter 前需要掌握什么?
1. 必须掌握
| 技能 | 说明 |
|---|---|
| Dart 基础 | Flutter 使用 Dart 开发,必须学 |
| 面向对象 | class、继承、抽象类、接口、泛型 |
| 异步编程 | Future、async、await、Stream |
| 组件化思想 | Flutter 页面由 Widget 组合而成 |
| HTTP 请求 | 对接后端接口 |
| 本地存储 | 保存 token、用户信息、缓存数据 |
| 路由跳转 | 页面之间切换 |
| 状态管理 | 控制数据变化和页面刷新 |
| 移动端基础 | Android / iOS 权限、打包、签名、上架 |
2. 前端开发者迁移 Flutter 的重点
如果你是前端开发,可以这样理解 Flutter:
text
Vue / React:HTML + CSS + JS
Flutter:Widget + Dart + 状态管理
Flutter 不写 HTML,也不写 CSS。页面样式、布局、交互都通过 Widget 完成。
例如前端这样写:
html
<div class="card">
<h2>标题</h2>
<p>内容</p>
</div>
Flutter 中通常这样写:
dart
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('标题', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text('内容'),
],
),
)
五、Flutter 开发环境搭建
1. 需要安装的软件
| 工具 | 作用 | 下载 / 文档 |
|---|---|---|
| Flutter SDK | Flutter 核心开发工具 | 点击打开 | https://docs.flutter.dev/get-started/install |
| Dart SDK | Dart 语言环境,Flutter SDK 通常自带 | 点击打开 | https://dart.dev/get-dart |
| Android Studio | Android SDK、模拟器、Gradle、打包工具 | 点击打开 | https://developer.android.com/studio |
| VS Code | 推荐代码编辑器 | 点击打开 | https://code.visualstudio.com/ |
| Xcode | macOS 开发 iOS 必备 | 点击打开 | https://developer.apple.com/xcode/ |
| Git | 版本管理工具 | 点击打开 | https://git-scm.com/ |
2. Windows 环境搭建步骤
第一步:下载 Flutter SDK
进入 Flutter 官方安装页:
https://docs.flutter.dev/get-started/install
下载 Windows 版本 SDK,解压到一个固定目录,例如:
text
D:\dev\flutter
不要放在中文路径、空格路径、系统权限复杂的目录下。
第二步:配置环境变量
把 Flutter 的 bin 目录加入系统 Path:
text
D:\dev\flutter\bin
配置完成后,打开命令行输入:
bash
flutter --version
如果能看到版本信息,说明 Flutter 命令配置成功。
第三步:安装 Android Studio
安装 Android Studio 后,需要安装:
- Android SDK
- Android SDK Platform-Tools
- Android SDK Build-Tools
- Android Emulator
- 至少一个 Android 系统镜像
第四步:执行环境检查
bash
flutter doctor
如果出现 Android license 报错,执行:
bash
flutter doctor --android-licenses
一路输入 y 同意即可。
六、Flutter 常用命令
| 命令 | 作用 |
|---|---|
flutter doctor |
检查 Flutter 环境 |
flutter create my_app |
创建 Flutter 项目 |
flutter run |
运行项目 |
flutter devices |
查看连接的设备 |
flutter pub get |
安装依赖 |
flutter pub add dio |
添加依赖 |
flutter pub remove dio |
删除依赖 |
flutter clean |
清理构建缓存 |
flutter analyze |
静态代码检查 |
dart format . |
格式化代码 |
flutter build apk |
构建 Android APK |
flutter build appbundle |
构建 Android AAB |
flutter build ios |
构建 iOS |
flutter build web |
构建 Web |
常见开发命令示例
bash
# 创建项目
flutter create flutter_demo
# 进入项目
cd flutter_demo
# 安装依赖
flutter pub get
# 启动项目
flutter run
# 添加 dio 请求库
flutter pub add dio
# 清理缓存
flutter clean
# 重新安装依赖
flutter pub get
七、Flutter 项目目录结构
创建项目后,默认目录一般是这样:
bash
my_app/
├── android/ # Android 原生工程
├── ios/ # iOS 原生工程
├── lib/ # 主要业务代码目录
│ └── main.dart # 入口文件
├── test/ # 测试代码
├── web/ # Web 配置
├── pubspec.yaml # 项目配置、依赖、资源声明
└── README.md
实际项目中,建议把 lib 改造成更清晰的企业级结构:
bash
lib/
├── main.dart
├── app.dart
├── core/
│ ├── constants/ # 常量
│ ├── utils/ # 工具函数
│ ├── theme/ # 主题配置
│ ├── router/ # 路由配置
│ ├── network/ # 网络请求封装
│ └── storage/ # 本地存储封装
├── data/
│ ├── models/ # 数据模型
│ ├── services/ # 底层服务
│ └── repositories/ # 数据仓库
├── features/
│ ├── login/ # 登录模块
│ │ ├── pages/
│ │ ├── widgets/
│ │ ├── models/
│ │ └── providers/
│ ├── home/
│ ├── profile/
│ └── appointment/
└── shared/
├── widgets/ # 公共组件
└── components/ # 通用业务组件
目录设计原则
core:放全局基础能力,例如网络、路由、主题、工具函数。features:按业务模块拆分,例如登录、首页、个人中心、预约。shared:放多个页面都会用到的公共组件。data:放接口数据、模型转换、仓库层逻辑。- 页面不要直接写复杂接口逻辑,尽量通过 Provider / Repository 调用。
八、Dart 基础语法
Flutter 使用 Dart 语言开发,所以先掌握 Dart 是必须的。
1. 变量
dart
void main() {
String name = '曾湛文';
int age = 22;
double price = 99.9;
bool isLogin = true;
// 自动推断类型
var city = '广州';
// 运行时确定,只能赋值一次
final token = 'abc123';
// 编译期常量
const appName = 'Flutter App';
print(name);
print(age);
print(city);
}
2. 函数
dart
int add(int a, int b) {
return a + b;
}
void main() {
print(add(10, 20));
}
简写:
dart
int add(int a, int b) => a + b;
3. 可选参数
dart
void printUser({required String name, int age = 18}) {
print('姓名:$name,年龄:$age');
}
void main() {
printUser(name: 'ZENG ZHANWEN');
printUser(name: 'ZENG ZHANWEN', age: 22);
}
4. 类和构造函数
dart
class User {
String name;
int age;
User(this.name, this.age);
void sayHello() {
print('你好,我是 $name,今年 $age 岁');
}
}
void main() {
final user = User('曾湛文', 22);
user.sayHello();
}
5. List 和 Map
dart
void main() {
final list = ['Vue', 'React', 'Flutter'];
print(list[0]);
final user = {
'name': '曾湛文',
'age': 22,
};
print(user['name']);
}
6. 异步 Future
dart
Future<String> getData() async {
await Future.delayed(const Duration(seconds: 1));
return '请求成功';
}
void main() async {
final result = await getData();
print(result);
}
7. 空安全
Dart 默认支持空安全。
dart
String name = 'Flutter';
// 可以为空
String? nickname;
void main() {
print(name);
print(nickname);
}
常见写法:
dart
String? token;
if (token != null) {
print(token.length);
}
九、Flutter 核心思想:万物皆 Widget
在 Flutter 中,几乎所有东西都是 Widget:
- 文字是 Widget。
- 图片是 Widget。
- 按钮是 Widget。
- 输入框是 Widget。
- 页面是 Widget。
- 布局也是 Widget。
- 动画也是 Widget。
1. StatelessWidget:无状态组件
适合不需要内部状态变化的组件。
dart
import 'package:flutter/material.dart';
class MyTitle extends StatelessWidget {
const MyTitle({super.key});
@override
Widget build(BuildContext context) {
return const Text(
'Flutter 学习',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
);
}
}
2. StatefulWidget:有状态组件
适合需要变化的数据,例如计数器、表单输入、登录状态、加载状态。
dart
import 'package:flutter/material.dart';
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int count = 0;
void add() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('计数器'),
),
body: Center(
child: Text(
'当前数量:$count',
style: const TextStyle(fontSize: 28),
),
),
floatingActionButton: FloatingActionButton(
onPressed: add,
child: const Icon(Icons.add),
),
);
}
}
3. Widget 生命周期
StatefulWidget 常见生命周期:
| 生命周期 | 作用 |
|---|---|
initState() |
初始化,只执行一次,常用于请求接口、初始化控制器 |
build() |
构建 UI,状态变化时可能多次执行 |
didUpdateWidget() |
父组件传入参数变化时触发 |
dispose() |
销毁组件,释放控制器、监听器、定时器 |
示例:
dart
@override
void initState() {
super.initState();
// 页面初始化时请求数据
}
@override
void dispose() {
// 释放资源
super.dispose();
}
十、Flutter 常用基础组件
1. Text 文本
dart
Text(
'Hello Flutter',
style: TextStyle(
fontSize: 20,
color: Colors.blue,
fontWeight: FontWeight.bold,
),
)
2. Image 图片
网络图片:
dart
Image.network('https://example.com/logo.png')
本地图片需要在 pubspec.yaml 中配置:
yaml
flutter:
assets:
- assets/images/
使用:
dart
Image.asset('assets/images/logo.png')
3. Icon 图标
dart
const Icon(
Icons.home,
size: 28,
color: Colors.blue,
)
4. Container 容器
dart
Container(
width: 200,
height: 100,
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
),
child: const Text('内容区域'),
)
5. ElevatedButton 按钮
dart
ElevatedButton(
onPressed: () {
print('点击按钮');
},
child: const Text('提交'),
)
6. TextField 输入框
dart
TextField(
decoration: InputDecoration(
labelText: '请输入用户名',
hintText: '例如 zengzhanwen',
border: OutlineInputBorder(),
),
)
7. Form 表单
dart
final formKey = GlobalKey<FormState>();
Form(
key: formKey,
child: TextFormField(
decoration: const InputDecoration(labelText: '手机号'),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入手机号';
}
return null;
},
),
)
提交校验:
dart
if (formKey.currentState!.validate()) {
print('表单校验通过');
}
8. Scaffold 页面骨架
dart
Scaffold(
appBar: AppBar(title: const Text('首页')),
body: const Center(child: Text('页面内容')),
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
],
),
)
十一、Flutter 布局系统
Flutter 布局和前端 CSS 不一样,但思想类似。
1. Column 纵向布局
dart
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text('标题'),
SizedBox(height: 8),
Text('内容'),
],
)
类似 CSS:
css
display: flex;
flex-direction: column;
2. Row 横向布局
dart
Row(
children: const [
Icon(Icons.home),
SizedBox(width: 8),
Text('首页'),
],
)
类似 CSS:
css
display: flex;
flex-direction: row;
3. Expanded 弹性布局
dart
Row(
children: [
Expanded(
child: Container(height: 50, color: Colors.red),
),
Expanded(
child: Container(height: 50, color: Colors.blue),
),
],
)
4. Stack 层叠布局
dart
Stack(
children: [
Image.network('https://example.com/banner.jpg'),
const Positioned(
left: 20,
bottom: 20,
child: Text('活动标题'),
),
],
)
类似前端:
css
position: relative;
position: absolute;
5. ListView 列表
dart
ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.article),
title: Text('第 $index 条数据'),
subtitle: const Text('这里是简介内容'),
);
},
)
6. GridView 网格
dart
GridView.builder(
itemCount: 20,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
return Container(
color: Colors.blue,
child: Center(child: Text('Item $index')),
);
},
)
7. Padding / Margin
Flutter 没有 CSS 中单独的 margin 属性,通常通过 Container.margin 或 Padding 实现。
dart
Padding(
padding: const EdgeInsets.all(16),
child: Text('内容'),
)
十二、Flutter 页面路由和跳转
Flutter 中页面跳转主要有两种方式:
Navigator原生路由。go_router路由库。
1. Navigator 普通跳转
dart
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DetailPage(),
),
);
返回上一页:
dart
Navigator.pop(context);
2. 使用 go_router
安装:
bash
flutter pub add go_router
配置路由:
dart
import 'package:go_router/go_router.dart';
final router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomePage(),
),
GoRoute(
path: '/detail/:id',
builder: (context, state) {
final id = state.pathParameters['id'];
return DetailPage(id: id!);
},
),
],
);
在 App 中使用:
dart
MaterialApp.router(
routerConfig: router,
)
跳转:
dart
context.go('/detail/1001');
3. 路由登录拦截思路
dart
final router = GoRouter(
redirect: (context, state) {
final isLogin = false;
final isLoginPage = state.uri.path == '/login';
if (!isLogin && !isLoginPage) {
return '/login';
}
return null;
},
routes: [
GoRoute(path: '/login', builder: (_, __) => const LoginPage()),
GoRoute(path: '/', builder: (_, __) => const HomePage()),
],
);
十三、Flutter 网络请求
小项目可以用 http,中大型项目更推荐 dio。
1. 使用 http
安装:
bash
flutter pub add http
示例:
dart
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> getUserList() async {
final url = Uri.parse('https://jsonplaceholder.typicode.com/users');
final response = await http.get(url);
if (response.statusCode == 200) {
final List data = jsonDecode(response.body);
print(data);
} else {
throw Exception('请求失败');
}
}
2. 使用 dio
安装:
bash
flutter pub add dio
封装 HttpClient:
dart
import 'package:dio/dio.dart';
class HttpClient {
static final Dio dio = Dio(
BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 10),
),
);
static Future<Response> get(String path, {Map<String, dynamic>? params}) {
return dio.get(path, queryParameters: params);
}
static Future<Response> post(String path, {dynamic data}) {
return dio.post(path, data: data);
}
}
调用:
dart
final res = await HttpClient.get('/user/list');
print(res.data);
3. 请求拦截器
dart
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {
options.headers['Authorization'] = 'Bearer token';
handler.next(options);
},
onResponse: (response, handler) {
handler.next(response);
},
onError: (error, handler) {
handler.next(error);
},
),
);
十四、JSON 模型转换
接口返回数据后,不建议在页面中直接使用 Map,最好定义 Model。
dart
class User {
final int id;
final String name;
final String email;
User({
required this.id,
required this.name,
required this.email,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
};
}
}
使用:
dart
final user = User.fromJson({
'id': 1,
'name': 'ZENG ZHANWEN',
'email': 'test@example.com',
});
print(user.name);
项目变大后推荐使用 json_serializable
安装:
bash
flutter pub add json_annotation
flutter pub add dev:build_runner
flutter pub add dev:json_serializable
这样可以自动生成 fromJson 和 toJson,减少手写错误。
十五、状态管理
Flutter 状态管理可以分为三类:
| 类型 | 适合场景 |
|---|---|
| setState | 页面内部小状态 |
| Provider | 中小型项目,简单易懂 |
| Riverpod | 中大型项目,结构清晰 |
| Bloc | 复杂业务、强规范团队项目 |
| GetX | 上手快,但大型项目要注意规范 |
1. setState
适合简单页面:
dart
setState(() {
count++;
});
缺点:状态只能在当前组件内管理,跨页面共享不方便。
2. Provider
安装:
bash
flutter pub add provider
定义状态:
dart
import 'package:flutter/material.dart';
class UserStore extends ChangeNotifier {
String username = '游客';
void login(String name) {
username = name;
notifyListeners();
}
void logout() {
username = '游客';
notifyListeners();
}
}
注册:
dart
ChangeNotifierProvider(
create: (_) => UserStore(),
child: const MyApp(),
)
使用:
dart
final userStore = context.watch<UserStore>();
Text('当前用户:${userStore.username}');
修改:
dart
context.read<UserStore>().login('曾湛文');
3. Riverpod
安装:
bash
flutter pub add flutter_riverpod
定义状态:
dart
final counterProvider = StateProvider<int>((ref) => 0);
页面使用:
dart
class CounterPage extends ConsumerWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
body: Center(child: Text('$count')),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(counterProvider.notifier).state++;
},
child: const Icon(Icons.add),
),
);
}
}
十六、本地存储
常见本地存储方案:
| 方案 | 适合存什么 |
|---|---|
| shared_preferences | token、主题、语言、简单配置 |
| flutter_secure_storage | 敏感 token、登录凭证 |
| sqflite | 本地关系型数据库 |
| hive / isar | 本地缓存、离线数据 |
| file | 图片、文件、日志 |
shared_preferences 示例
安装:
bash
flutter pub add shared_preferences
保存 token:
dart
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', 'abc123');
读取 token:
dart
final token = prefs.getString('token');
删除 token:
dart
await prefs.remove('token');
建议
- 普通配置:用
shared_preferences。 - 敏感信息:优先用
flutter_secure_storage。 - 大量离线数据:考虑
isar、hive或sqflite。
十七、登录注册与 Token 拦截
Flutter 登录注册流程和前端项目很像。
1. 基本流程
text
用户输入账号密码
↓
前端校验表单
↓
调用登录接口
↓
后端返回 token / 用户信息
↓
保存 token 到本地
↓
跳转首页
↓
后续请求在 Header 中携带 token
2. 登录伪代码
dart
Future<void> login(String username, String password) async {
final res = await HttpClient.post('/login', data: {
'username': username,
'password': password,
});
final token = res.data['token'];
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', token);
}
3. dio 请求自动携带 token
dart
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) async {
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('token');
if (token != null) {
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options);
},
onError: (error, handler) {
if (error.response?.statusCode == 401) {
// token 失效:清除本地 token,跳转登录页
}
handler.next(error);
},
),
);
4. 登录状态管理建议
建议建立一个 AuthProvider:
dart
class AuthProvider extends ChangeNotifier {
String? token;
bool get isLogin => token != null;
Future<void> login(String username, String password) async {
// 调用登录接口
token = 'server-token';
notifyListeners();
}
Future<void> logout() async {
token = null;
notifyListeners();
}
}
十八、权限、图片上传、WebView、地图和推送
真实 App 经常会用到系统能力。
1. 权限申请
推荐包:permission_handler
bash
flutter pub add permission_handler
示例:
dart
final status = await Permission.camera.request();
if (status.isGranted) {
print('相机权限已授权');
} else {
print('相机权限被拒绝');
}
常见权限:
| 权限 | 场景 |
|---|---|
| 相机 | 拍照上传头像、上传病历 |
| 相册 | 选择图片 |
| 定位 | 地图、附近医院、地址选择 |
| 通知 | 消息推送 |
| 麦克风 | 语音聊天、录音 |
2. 图片选择
推荐包:image_picker
bash
flutter pub add image_picker
示例:
dart
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) {
print(image.path);
}
3. WebView
推荐包:webview_flutter
bash
flutter pub add webview_flutter
适合场景:
- 内嵌官网页面。
- 内嵌活动页。
- 内嵌隐私协议。
- 内嵌支付页面。
4. 地图
常见选择:
| 地图 | 说明 |
|---|---|
| Google Maps | 海外项目常用 |
| 高德地图 | 国内项目常用 |
| 百度地图 | 国内项目可选 |
5. 推送
常见选择:
| 推送方案 | 说明 |
|---|---|
| Firebase Cloud Messaging | 海外 App 常用 |
| 极光推送 | 国内项目常用 |
| 个推 | 国内项目常用 |
| 厂商推送 | 华为、小米、OPPO、vivo 等 |
十九、企业级 Flutter 项目架构
大型 Flutter 项目不要把所有代码写在页面里,要做分层。
1. 推荐分层
text
UI 层
↓
状态管理层 / ViewModel
↓
Repository 数据仓库层
↓
Service 服务层
↓
API / Storage / Native 能力
2. UI 层
负责页面展示:
- Page
- Widget
- Component
- Dialog
- Form
不要在 UI 层直接写复杂业务逻辑。
3. Provider / ViewModel 层
负责页面状态:
- loading
- error
- list
- form
- pagination
- selected item
- submit status
4. Repository 层
负责统一管理数据来源:
- 调用接口。
- 读取缓存。
- 处理数据转换。
- 屏蔽底层数据来源差异。
5. Service 层
负责底层能力:
- HTTP
- Storage
- Location
- Camera
- Permission
- Analytics
- Push
6. 推荐目录结构
bash
lib/
├── main.dart
├── app.dart
├── core/
│ ├── network/http_client.dart
│ ├── router/app_router.dart
│ ├── storage/storage.dart
│ ├── theme/app_theme.dart
│ └── utils/toast.dart
├── data/
│ ├── models/user.dart
│ ├── repositories/auth_repository.dart
│ └── services/auth_service.dart
├── features/
│ ├── auth/
│ │ ├── pages/login_page.dart
│ │ ├── pages/register_page.dart
│ │ └── providers/auth_provider.dart
│ ├── home/
│ ├── consultation/
│ ├── appointment/
│ └── profile/
└── shared/
├── widgets/app_button.dart
├── widgets/app_input.dart
└── widgets/loading_view.dart
二十、完整项目实战:医疗咨询预约 App
这个项目比较接近真实业务,适合练习 Flutter 的完整能力。
1. 项目功能
| 模块 | 功能 |
|---|---|
| 登录注册 | 手机号、验证码、密码登录 |
| 首页 | Banner、科室入口、专家推荐、健康文章 |
| 文章列表 | 分类、分页、搜索 |
| 文章详情 | 富文本、图片、收藏、分享 |
| 在线咨询 | 表单提交、病情描述、图片上传 |
| 预约挂号 | 选择科室、医生、时间、联系方式 |
| 个人中心 | 用户资料、我的预约、设置 |
| 设置 | 语言切换、主题切换、退出登录 |
2. 技术栈
| 类型 | 技术 |
|---|---|
| 开发框架 | Flutter |
| 开发语言 | Dart |
| 路由 | go_router |
| 网络请求 | dio |
| 状态管理 | Provider / Riverpod |
| 本地存储 | shared_preferences / flutter_secure_storage |
| 图片上传 | image_picker + dio FormData |
| 权限 | permission_handler |
| WebView | webview_flutter |
3. 页面结构
text
LoginPage 登录页
HomePage 首页
ArticleListPage 文章列表页
ArticleDetailPage 文章详情页
ConsultationPage 在线咨询页
AppointmentPage 预约页
ProfilePage 个人中心页
SettingPage 设置页
4. 接口设计示例
| 接口 | 方法 | 说明 |
|---|---|---|
/api/login |
POST | 登录 |
/api/register |
POST | 注册 |
/api/articles |
GET | 文章列表 |
/api/articles/:id |
GET | 文章详情 |
/api/consultation |
POST | 提交咨询 |
/api/upload |
POST | 图片上传 |
/api/appointments |
POST | 创建预约 |
/api/user/profile |
GET | 用户信息 |
5. 咨询表单页面示例
dart
class ConsultationPage extends StatefulWidget {
const ConsultationPage({super.key});
@override
State<ConsultationPage> createState() => _ConsultationPageState();
}
class _ConsultationPageState extends State<ConsultationPage> {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final phoneController = TextEditingController();
final descController = TextEditingController();
Future<void> submit() async {
if (!formKey.currentState!.validate()) return;
final data = {
'name': nameController.text,
'phone': phoneController.text,
'description': descController.text,
};
// 这里调用接口提交
print(data);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('在线咨询')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Form(
key: formKey,
child: Column(
children: [
TextFormField(
controller: nameController,
decoration: const InputDecoration(labelText: '姓名'),
validator: (value) => value == null || value.isEmpty ? '请输入姓名' : null,
),
const SizedBox(height: 12),
TextFormField(
controller: phoneController,
decoration: const InputDecoration(labelText: '电话'),
validator: (value) => value == null || value.isEmpty ? '请输入电话' : null,
),
const SizedBox(height: 12),
TextFormField(
controller: descController,
maxLines: 4,
decoration: const InputDecoration(labelText: '病情描述'),
validator: (value) => value == null || value.isEmpty ? '请输入病情描述' : null,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: submit,
child: const Text('提交咨询'),
),
],
),
),
),
);
}
}
二十一、Flutter 屏幕适配
移动端要考虑不同屏幕尺寸、刘海屏、状态栏、底部安全区、横竖屏和字体大小。
1. SafeArea
避免内容被刘海、状态栏、底部安全区挡住。
dart
SafeArea(
child: Scaffold(
body: Text('安全区域内容'),
),
)
2. MediaQuery
获取屏幕宽高:
dart
final size = MediaQuery.of(context).size;
final width = size.width;
final height = size.height;
3. LayoutBuilder
根据父容器大小做响应式布局:
dart
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return TabletLayout();
} else {
return MobileLayout();
}
},
)
4. flutter_screenutil
安装:
bash
flutter pub add flutter_screenutil
适合用来处理不同手机尺寸下的宽高、字体和间距。
二十二、Flutter 动画
1. 隐式动画
适合简单动画:
dart
AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: isBig ? 200 : 100,
height: isBig ? 200 : 100,
color: isBig ? Colors.blue : Colors.red,
)
2. 显式动画
复杂动画常用:
- AnimationController
- Tween
- AnimatedBuilder
- FadeTransition
- ScaleTransition
- SlideTransition
示例:
dart
class FadeBox extends StatefulWidget {
const FadeBox({super.key});
@override
State<FadeBox> createState() => _FadeBoxState();
}
class _FadeBoxState extends State<FadeBox>
with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation<double> animation;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
animation = Tween<double>(begin: 0, end: 1).animate(controller);
controller.forward();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: animation,
child: const Text('淡入动画'),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
3. Lottie 动画
安装:
bash
flutter pub add lottie
使用:
dart
Lottie.asset('assets/animations/loading.json')
适合加载动画、空状态、成功提示、活动效果。
二十三、Flutter 性能优化
1. UI 优化
| 优化方式 | 说明 |
|---|---|
使用 const |
减少不必要重建 |
| 拆分 Widget | 避免一个大 build 方法过重 |
| ListView.builder | 长列表按需渲染 |
| 避免 build 中复杂计算 | 复杂计算提前处理 |
| 图片压缩 | 减少内存占用 |
| 合理使用缓存 | 避免重复请求 |
2. 状态优化
- 不要全页面频繁
setState。 - 能局部刷新的地方,不要全局刷新。
- Provider / Riverpod 中拆分状态粒度。
- 列表项尽量独立成小组件。
3. 网络优化
- 接口分页加载。
- 请求失败重试。
- 图片懒加载。
- 数据缓存。
- 防抖搜索。
- 上传图片前压缩。
4. 工具分析
推荐使用 Flutter DevTools 分析性能、内存、网络、布局和日志。
Flutter DevTools 文档:
https://docs.flutter.dev/tools/devtools
二十四、Flutter Android 打包发布流程
1. Android 发布前需要准备
| 项目 | 说明 |
|---|---|
| 应用名称 | 用户看到的 App 名称 |
| 包名 | 例如 com.example.myapp,上线后不要随便改 |
| 图标 | 多尺寸图标 |
| 权限 | 相机、相册、定位、通知等 |
| 签名文件 | release 版本必须配置 |
| 隐私政策 | 应用市场通常要求 |
| 版本号 | versionCode / versionName |
2. 修改应用名称
Android 目录中通常在:
text
android/app/src/main/AndroidManifest.xml
查找:
xml
android:label="你的应用名称"
3. 配置签名
生成 keystore:
bash
keytool -genkey -v -keystore upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
创建 android/key.properties:
properties
storePassword=你的密码
keyPassword=你的密码
keyAlias=upload
storeFile=../upload-keystore.jks
配置 android/app/build.gradle 或 build.gradle.kts 中的 release signing。
4. 构建 APK
bash
flutter build apk --release
5. 构建 AAB
Google Play 更常用 AAB:
bash
flutter build appbundle --release
6. 国内 Android 应用市场常见要求
| 应用市场 | 常见要求 |
|---|---|
| 华为应用市场 | 软著、隐私政策、权限说明、备案信息 |
| 小米应用商店 | 隐私政策、权限合规、应用截图 |
| OPPO / vivo | 账号认证、版权证明、隐私协议 |
| 应用宝 | 腾讯开放平台账号、隐私政策、审核资料 |
二十五、Flutter iOS 打包发布流程
1. iOS 发布需要准备
| 项目 | 说明 |
|---|---|
| Apple Developer 账号 | 必须付费开发者账号 |
| App Store Connect | 创建 App 信息 |
| Bundle Identifier | 应用唯一标识 |
| 证书 | Development / Distribution |
| 描述文件 | Provisioning Profile |
| 隐私清单 | 权限和数据采集合规 |
| 应用截图 | iPhone / iPad 尺寸截图 |
2. 常用命令
bash
flutter build ios --release
通常还需要用 Xcode 打开:
bash
open ios/Runner.xcworkspace
然后在 Xcode 中执行:
text
Product → Archive → Distribute App
3. iOS 常见审核注意点
- 隐私政策必须真实可访问。
- 权限用途说明要清楚。
- 如果有登录,最好提供测试账号。
- 支付相关功能要符合 App Store 规则。
- 不要包含诱导下载、违规广告、虚假医疗承诺等内容。
二十六、Flutter 常见报错与解决方案
1. flutter doctor 报错
常见原因:
text
Android SDK 没装
Android license 没同意
环境变量没配置
Xcode 没安装
CocoaPods 没安装
模拟器没启动
解决:
bash
flutter doctor
flutter doctor --android-licenses
flutter clean
flutter pub get
2. Android 打包失败
常见原因:
text
Gradle 版本不兼容
JDK 版本不匹配
签名配置错误
包名重复
第三方插件 Android 配置错误
解决思路:
- 检查 JDK 版本。
- 检查 Gradle 配置。
- 执行
flutter clean。 - 删除 build 缓存后重新构建。
- 查看具体报错行,而不是只看最后一行。
3. iOS 打包失败
常见原因:
text
证书错误
Bundle Identifier 不一致
Provisioning Profile 不匹配
CocoaPods 依赖异常
Xcode 版本不兼容
常用命令:
bash
cd ios
pod install
pod update
cd ..
flutter clean
flutter pub get
4. 页面卡顿
优化方向:
text
减少 build 中的复杂计算
列表使用 ListView.builder
图片做压缩和缓存
避免无意义 setState
大组件拆小组件
使用 const Widget
避免一次性渲染大量数据
5. 依赖冲突
解决方式:
bash
flutter pub outdated
flutter pub upgrade
flutter pub get
如果升级后报错,需要查看对应包的 changelog 和迁移说明。
二十七、Flutter 学习路线
第一阶段:Dart 基础
学习内容:
text
变量
函数
类
构造函数
继承
泛型
空安全
Future
async / await
Stream
List / Map
目标:能看懂 Flutter 代码。
第二阶段:Flutter 基础组件
学习内容:
text
Text
Image
Icon
Button
Container
Row
Column
Stack
ListView
GridView
Scaffold
AppBar
BottomNavigationBar
Dialog
Form
TextField
目标:能独立写页面。
第三阶段:项目基础能力
学习内容:
text
路由跳转
网络请求
JSON 转 Model
本地存储
登录注册
token 拦截
图片上传
权限申请
下拉刷新
分页加载
目标:能做完整业务 App。
第四阶段:状态管理和架构
学习内容:
text
Provider
Riverpod
Bloc
MVVM
Repository
Service
依赖注入
错误处理
全局状态
主题切换
多语言
目标:能写企业级项目。
第五阶段:打包发布
学习内容:
text
Android 签名
APK / AAB
iOS 证书
App Store Connect
应用市场审核
隐私权限配置
版本更新
崩溃收集
性能优化
目标:能独立上线 App。
六周学习计划
| 周数 | 学习内容 | 目标 |
|---|---|---|
| 第 1 周 | Dart 基础、Flutter 环境、基础组件 | 能运行项目,写简单页面 |
| 第 2 周 | 布局、表单、列表、图片、页面跳转 | 能完成常见 App 页面 |
| 第 3 周 | 网络请求、Model、本地存储、登录注册 | 能对接后端接口 |
| 第 4 周 | 状态管理、路由守卫、权限、上传 | 能实现完整业务流程 |
| 第 5 周 | 项目架构、公共组件、主题、多语言 | 能写可维护项目 |
| 第 6 周 | Android / iOS 打包、性能优化、上线审核 | 能发布真实 App |
二十八、Flutter 练手项目推荐
| 项目 | 练习重点 | 推荐指数 |
|---|---|---|
| Todo App | 状态管理、本地存储 | ⭐⭐⭐ |
| 记账 App | 表单、图表、本地数据库 | ⭐⭐⭐⭐ |
| 天气 App | 网络请求、定位、UI 展示 | ⭐⭐⭐⭐ |
| 新闻资讯 App | 列表、详情、分页、缓存 | ⭐⭐⭐⭐ |
| 商城 App | 登录、商品、购物车、订单 | ⭐⭐⭐⭐⭐ |
| 医疗咨询 App | 表单、上传、预约、用户中心 | ⭐⭐⭐⭐⭐ |
| 企业数据看板 App | 图表、权限、接口封装 | ⭐⭐⭐⭐ |
| 短视频 App | 视频播放、列表滑动、缓存 | ⭐⭐⭐⭐ |
最推荐你先做:
- 登录注册 + 首页 + 个人中心 App。
- 医疗咨询预约 App。
- 商城 App。
这三个项目最接近真实业务,能练到接口、状态、路由、表单、上传、缓存、打包发布。
二十九、Flutter 面试常考题
1. Flutter 是什么?
Flutter 是 Google 推出的跨平台 UI 框架,使用 Dart 语言开发,可以用一套代码构建 Android、iOS、Web、桌面端等多平台应用。
2. Flutter 和 React Native 有什么区别?
Flutter 使用 Dart 和自绘渲染引擎,UI 一致性强。React Native 使用 JavaScript / TypeScript,更多依赖原生组件。Flutter 在动画、UI 一致性、跨平台表现上优势明显,React Native 对前端 React 团队更友好。
3. StatelessWidget 和 StatefulWidget 的区别?
StatelessWidget 是无状态组件,适合静态 UI。StatefulWidget 是有状态组件,适合需要数据变化的 UI,例如计数器、表单、登录状态。
4. setState 有什么问题?
setState 简单直接,但只适合局部状态。项目变大后,如果跨页面共享状态,代码会难维护,所以需要 Provider、Riverpod、Bloc 等状态管理方案。
5. Flutter 如何做登录拦截?
登录成功后保存 token。请求时通过拦截器自动添加 token。接口返回 401 时清除 token 并跳转登录页。路由层也可以根据登录状态限制访问页面。
6. Flutter 如何优化性能?
常见方式:
text
使用 const 构造
拆分 Widget
避免 build 中写复杂逻辑
列表使用 builder
图片压缩和缓存
减少不必要 setState
使用 DevTools 分析性能
7. Flutter 中 Future 和 Stream 的区别?
Future 表示一次异步结果,例如接口请求。Stream 表示连续异步数据流,例如倒计时、WebSocket、文件下载进度。
8. Flutter 如何做接口封装?
通常基于 dio 封装 HttpClient,统一处理 baseUrl、超时、请求头、token、错误码、刷新 token、日志和异常提示。
9. Flutter 如何做本地存储?
简单数据用 shared_preferences,敏感数据用 flutter_secure_storage,复杂结构化数据用 sqflite、hive 或 isar。
10. Flutter 如何解决页面卡顿?
使用 ListView.builder、减少重复构建、拆分组件、压缩图片、使用缓存、避免在 build 中执行复杂逻辑,并使用 DevTools 分析性能。
三十、Flutter 资源与文档汇总
说明:下面所有资源都同时提供"可点击链接"和"明文网址",方便你复制到 Markdown、博客、公众号或者笔记里。
1. 官方核心资源
| 类型 | 名称 | 可点击链接 | 明文网址 |
|---|---|---|---|
| Flutter 官网 | Flutter 官方首页 | 点击跳转 | https://flutter.dev/ |
| Flutter 文档 | Flutter 官方文档 | 点击跳转 | https://docs.flutter.dev/ |
| Flutter 安装 | Flutter 安装教程 | 点击跳转 | https://docs.flutter.dev/get-started/install |
| Flutter Release Notes | Flutter 版本发布记录 | 点击跳转 | https://docs.flutter.dev/release/release-notes |
| Flutter What's New | Flutter 文档更新 | 点击跳转 | https://docs.flutter.dev/release/whats-new |
| Flutter API | Flutter API 文档 | 点击跳转 | https://api.flutter.dev/ |
| Flutter GitHub | Flutter 源码仓库 | 点击跳转 | https://github.com/flutter/flutter |
| Flutter YouTube | Flutter 官方视频频道 | 点击跳转 | https://www.youtube.com/@flutterdev |
2. Dart 语言资源
| 类型 | 名称 | 可点击链接 | 明文网址 |
|---|---|---|---|
| Dart 官网 | Dart 官方首页 | 点击跳转 | https://dart.dev/ |
| Dart 文档 | Dart 官方文档 | 点击跳转 | https://dart.dev/docs |
| Dart 语言教程 | Language Tour | 点击跳转 | https://dart.dev/language |
| Effective Dart | Dart 编码规范 | 点击跳转 | https://dart.dev/effective-dart |
| Dart 包管理 | Dart Packages | 点击跳转 | https://dart.dev/tools/pub/packages |
3. Flutter 项目开发文档
| 类型 | 名称 | 可点击链接 | 明文网址 |
|---|---|---|---|
| Widget 目录 | Flutter Widget Catalog | 点击跳转 | https://docs.flutter.dev/ui/widgets |
| 布局教程 | Flutter Layout | 点击跳转 | https://docs.flutter.dev/ui/layout |
| 导航路由 | Flutter Navigation | 点击跳转 | https://docs.flutter.dev/ui/navigation |
| 网络请求 | Fetch data from the internet | 点击跳转 | https://docs.flutter.dev/cookbook/networking/fetch-data |
| 状态管理 | Flutter State Management | 点击跳转 | https://docs.flutter.dev/data-and-backend/state-mgmt |
| App 架构 | Flutter App Architecture | 点击跳转 | https://docs.flutter.dev/app-architecture |
| DevTools | Flutter DevTools | 点击跳转 | https://docs.flutter.dev/tools/devtools |
| 性能优化 | Flutter Performance | 点击跳转 | https://docs.flutter.dev/perf |
4. 打包发布文档
| 类型 | 名称 | 可点击链接 | 明文网址 |
|---|---|---|---|
| Android 发布 | Flutter Android Deployment | 点击跳转 | https://docs.flutter.dev/deployment/android |
| iOS 发布 | Flutter iOS Deployment | 点击跳转 | https://docs.flutter.dev/deployment/ios |
| Web 发布 | Flutter Web Deployment | 点击跳转 | https://docs.flutter.dev/deployment/web |
| macOS 发布 | Flutter macOS Deployment | 点击跳转 | https://docs.flutter.dev/deployment/macos |
| Windows 发布 | Flutter Windows Deployment | 点击跳转 | https://docs.flutter.dev/deployment/windows |
| Linux 发布 | Flutter Linux Deployment | 点击跳转 | https://docs.flutter.dev/deployment/linux |
| Google Play Console | Google Play 管理后台 | 点击跳转 | https://play.google.com/console |
| App Store Connect | Apple App Store 后台 | 点击跳转 | https://appstoreconnect.apple.com/ |
| Apple Developer | Apple 开发者平台 | 点击跳转 | https://developer.apple.com/ |
5. 常用插件资源
6. Android / iOS 原生相关资源
| 类型 | 名称 | 可点击链接 | 明文网址 |
|---|---|---|---|
| Android Studio | Android Studio 下载 | 点击跳转 | https://developer.android.com/studio |
| Android 文档 | Android Developers | 点击跳转 | https://developer.android.com/ |
| Android 签名 | Sign your app | 点击跳转 | https://developer.android.com/studio/publish/app-signing |
| Xcode | Xcode 官方页 | 点击跳转 | https://developer.apple.com/xcode/ |
| App Store 审核 | App Review Guidelines | 点击跳转 | https://developer.apple.com/app-store/review/guidelines/ |
| Human Interface Guidelines | Apple 设计规范 | 点击跳转 | https://developer.apple.com/design/human-interface-guidelines |
| Material Design | Google 设计规范 | 点击跳转 | https://m3.material.io/ |
三十一、总结
Flutter 的学习重点不是死记组件,而是掌握完整 App 开发链路:
text
Dart 语法
↓
Widget 组件
↓
布局系统
↓
路由跳转
↓
接口请求
↓
状态管理
↓
本地存储
↓
登录权限
↓
项目架构
↓
性能优化
↓
打包上线
如果你是前端开发工程师,建议不要只看语法,而是直接围绕一个真实项目练习:
登录注册 + 首页列表 + 文章详情 + 在线咨询 + 图片上传 + 个人中心 + token 拦截 + 本地缓存 + Android / iOS 打包。
这样学习效率最高,也最容易把 Flutter 转化成真正的项目能力。🔥