Flutter开发
概览
使用Flutter和Dart语言创建高性能、视觉震撼的移动应用。掌握组件组合、状态管理模式、导航和API集成。
何时使用
- 构建具有原生性能的iOS和Android应用
- 使用Flutter的组件系统设计自定义UI
- 实施复杂的动画和视觉效果
- 通过热重载快速应用开发
- 在平台间创建一致的用户体验
指令
1. 项目结构与导航
// pubspec.yaml
名称: my_flutter_app
版本: 1.0.0
依赖:
flutter:
sdk: flutter
提供者: ^6.0.0
http: ^1.1.0
go_router: ^12.0.0
// main.dart与GoRouter导航
导入 'package:flutter/material.dart';
导入 'package:go_router/go_router.dart';
void main() {
runApp(const MyApp());
}
类 MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
标题: 'Flutter App',
主题: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
路由器配置: _router,
);
}
}
final GoRouter _router = GoRouter(
路由: <RouteBase>[
GoRoute(
路径: '/',
构建器: (context, state) => const HomeScreen(),
路由: [
GoRoute(
路径: 'details/:id',
构建器: (context, state) => DetailsScreen(
itemId: state.pathParameters['id']!
),
),
],
),
GoRoute(
路径: '/profile',
构建器: (context, state) => const ProfileScreen(),
),
],
);
2. 使用Provider的状态管理
导入 'package:flutter/material.dart';
导入 'package:http/http.dart' as http;
导入 'dart:convert';
类 User {
最终 String id;
最终 String name;
最终 String email;
User({required this.id, required this.name, required this.email});
工厂 User.fromJson(Map<String, dynamic> json) {
返回 User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
}
类 UserProvider extends ChangeNotifier {
User? _user;
布尔 _isLoading = false;
String? _error;
User? get user => _user;
布尔 get isLoading => _isLoading;
String? get error => _error;
未来<void> fetchUser(String userId) async {
_isLoading = true;
_error = null;
通知监听者();
try {
最终响应 = await http.get(
Uri.parse('https://api.example.com/users/$userId'),
头: {'Content-Type': 'application/json'},
);
如果 (response.statusCode == 200) {
_user = User.fromJson(jsonDecode(response.body));
} else {
_error = 'Failed to fetch user';
}
} catch (e) {
_error = 'Error: ${e.toString()}';
} finally {
_isLoading = false;
通知监听者();
}
}
退出() {
_user = null;
通知监听者();
}
}
类 ItemsProvider extends ChangeNotifier {
List<Map<String, dynamic>> _items = [];
List<Map<String, dynamic>> get items => _items;
未来<void> fetchItems() async {
try {
final response = await http.get(
Uri.parse('https://api.example.com/items'),
);
如果 (response.statusCode == 200) {
_items = List<Map<String, dynamic>>.from(
jsonDecode(response.body)作为列表
);
通知监听者();
}
} catch (e) {
打印('Error fetching items: $e');
}
}
}
3. 带有Provider集成的屏幕
类 HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
类 _HomeScreenState extends State<HomeScreen> {
@override
void initState() {
超.initState();
未来.microtask(() {
Provider.of<ItemsProvider>(context, listen: false).fetchItems();
});
}
@override
Widget build(BuildContext context) {
返回 Scaffold(
appbar: AppBar(title: const Text('Home Feed')),
身体: Consumer<ItemsProvider>(
构建器: (context, itemsProvider, child) {
如果 (itemsProvider.items.isEmpty) {
返回 const Center(child: Text('No items found'));
}
返回 ListView.builder(
项目计数: itemsProvider.items.length,
项目构建器: (context, index) {
最终项目 = itemsProvider.items[index];
返回 ItemCard(item: item);
},
);
},
),
);
}
}
类 ItemCard extends StatelessWidget {
最终 Map<String, dynamic> item;
构造 ItemCard({required this.item, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
返回 Card(
边距: const EdgeInsets.all(8),
孩子: ListTile(
标题: Text(item['title'] ?? 'Untitled'),
副标题: Text(item['description'] ?? ''),
尾随: const Icon(Icons.arrow_forward),
onTap: () => context.go('/details/${item['id']}'),
),
);
}
}
类 DetailsScreen extends StatelessWidget {
最终 String itemId;
构造 DetailsScreen({required this.itemId, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
返回 Scaffold(
appbar: AppBar(title: const Text('Details')),
身体: Center(
孩子: 列(
mainAxisAlignment: MainAxisAlignment.center,
孩子: [
Text('Item ID: $itemId', 风格: const TextStyle(fontSize: 18)),
const SizedBox(height: 16),
ElevatedButton(
按下: () => context.pop(),
孩子: const Text('Go Back'),
),
],
),
),
);
}
}
类 ProfileScreen extends StatelessWidget {
构造 ProfileScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
返回 Scaffold(
appbar: AppBar(title: const Text('Profile')),
身体: Consumer<UserProvider>(
构建器: (context, userProvider, child) {
如果 (userProvider.isLoading) {
返回 const Center(child: CircularProgressIndicator());
}
如果 (userProvider.error != null) {
返回 Center(child: Text('Error: ${userProvider.error}'));
}
最终用户 = userProvider.user;
如果 (user == null) {
返回 const Center(child: Text('No user data'));
}
返回 Padding(
填充: const EdgeInsets.all(16),
孩子: 列(
crossAxisAlignment: CrossAxisAlignment.start,
孩子: [
Text('Name: ${user.name}', 风格: const TextStyle(fontSize: 18)),
Text('Email: ${user.email}', 风格: const TextStyle(fontSize: 16)),
const SizedBox(height: 16),
ElevatedButton(
按下: () => userProvider.logout(),
孩子: const Text('Logout'),
),
],
),
);
},
),
);
}
}
最佳实践
✅ DO
- 对每个UI元素使用组件
- 实施适当的状态管理
- 尽可能使用const构造函数
- 在状态生命周期中处置资源
- 在多个设备尺寸上测试
- 使用有意义的组件名称
- 实施错误处理
- 使用响应式设计模式
- 在iOS和Android上进行测试
- 为自定义组件编写文档
❌ DON’T
- 在build()方法中构建整个屏幕
- 使用setState进行复杂状态逻辑
- 在build()中进行网络调用
- 忽略平台差异
- 创建过度嵌套的组件树
- 硬编码字符串
- 忽略性能警告
- 跳过测试
- 忘记处理边缘情况
- 在没有彻底测试的情况下部署