3_flutter简单教程
Flutter 简单教程
概述
Flutter是Google开发的跨平台移动应用开发框架,使用Dart语言编写。本教程将从UI设计和代码逻辑两个方面介绍Flutter应用开发。
一、UI开发方面
1. Widget基础
Flutter应用由Widget组成,Widget是Flutter的基本构建块。
常用Widget类型
// 基础Widget
Text('Hello World')
Image.asset('assets/image.png')
Icon(Icons.star)
// 布局Widget
Container(
width: 100,
height: 100,
color: Colors.blue,
)
Column(
children: [
Text('Item 1'),
Text('Item 2'),
],
)
Row(
children: [
Icon(Icons.star),
Text('Rating'),
],
)
2. 页面布局
Material Design风格
import 'package:flutter/material.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('我的应用'),
backgroundColor: Colors.blue,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'欢迎使用Flutter!',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 按钮点击事件
},
child: Text('点击我'),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// FAB点击事件
},
child: Icon(Icons.add),
),
);
}
}
Cupertino风格(iOS风格)
import 'package:flutter/cupertino.dart';
class IosStylePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('iOS风格页面'),
),
child: Center(
child: CupertinoButton(
onPressed: () {},
child: Text('iOS风格按钮'),
),
),
);
}
}
3. 响应式设计
媒体查询
class ResponsiveLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 获取屏幕尺寸
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
return Container(
width: screenWidth > 600 ? 300 : 200, // 根据屏幕宽度调整
height: screenHeight * 0.5, // 屏幕高度的50%
child: Text('响应式布局'),
);
}
}
自适应布局
class AdaptiveLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
// 平板或桌面布局
return Row(
children: [
Expanded(flex: 1, child: Sidebar()),
Expanded(flex: 3, child: MainContent()),
],
);
} else {
// 手机布局
return Column(
children: [
Expanded(child: MainContent()),
BottomNavigation(),
],
);
}
},
);
}
}
4. 动画和过渡
简单动画
class AnimatedContainerExample extends StatefulWidget {
@override
_AnimatedContainerExampleState createState() => _AnimatedContainerExampleState();
}
class _AnimatedContainerExampleState extends State<AnimatedContainerExample> {
bool _expanded = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
_expanded = !_expanded;
});
},
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
width: _expanded ? 200 : 100,
height: _expanded ? 200 : 100,
color: _expanded ? Colors.blue : Colors.red,
child: Center(child: Text('点击动画')),
),
);
}
}
二、代码后端逻辑方面
1. 状态管理
setState方法(简单状态)
class CounterApp extends StatefulWidget {
@override
_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int _counter = 0;
/// 增加计数器
void _incrementCounter() {
setState(() {
_counter++;
});
}
/// 减少计数器
void _decrementCounter() {
setState(() {
_counter--;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('计数器: $_counter', style: TextStyle(fontSize: 24)),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _decrementCounter,
child: Text('-'),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('+'),
),
],
),
],
),
),
);
}
}
Provider状态管理(推荐)
import 'package:provider/provider.dart';
// 数据模型
class UserModel with ChangeNotifier {
String _name = '';
int _age = 0;
String get name => _name;
int get age => _age;
/// 更新用户信息
void updateUser(String newName, int newAge) {
_name = newName;
_age = newAge;
notifyListeners(); // 通知监听器更新UI
}
}
// 使用Provider
class UserProfile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<UserModel>(
builder: (context, user, child) {
return Column(
children: [
Text('姓名: ${user.name}'),
Text('年龄: ${user.age}'),
ElevatedButton(
onPressed: () {
user.updateUser('张三', 25);
},
child: Text('更新用户'),
),
],
);
},
);
}
}
2. 数据持久化
SharedPreferences(本地存储)
import 'package:shared_preferences/shared_preferences.dart';
class SettingsService {
static const String _themeKey = 'theme';
static const String _languageKey = 'language';
/// 保存主题设置
static Future<void> saveTheme(String theme) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_themeKey, theme);
}
/// 获取主题设置
static Future<String?> getTheme() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_themeKey);
}
/// 保存语言设置
static Future<void> saveLanguage(String language) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_languageKey, language);
}
/// 获取语言设置
static Future<String?> getLanguage() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_languageKey);
}
}
SQLite数据库
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = DatabaseHelper._internal();
static Database? _database;
DatabaseHelper._internal();
factory DatabaseHelper() => _instance;
/// 获取数据库实例
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
/// 初始化数据库
Future<Database> _initDatabase() async {
String path = join(await getDatabasesPath(), 'my_database.db');
return await openDatabase(
path,
version: 1,
onCreate: _createTables,
);
}
/// 创建数据表
Future<void> _createTables(Database db, int version) async {
await db.execute('''
CREATE TABLE users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL,
created_at TEXT
)
''');
}
/// 插入用户
Future<int> insertUser(Map<String, dynamic> user) async {
final db = await database;
return await db.insert('users', user);
}
/// 查询所有用户
Future<List<Map<String, dynamic>>> getUsers() async {
final db = await database;
return await db.query('users');
}
}
3. 网络请求
HTTP请求
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
static const String baseUrl = 'https://api.example.com';
/// 获取用户列表
static Future<List<dynamic>> getUsers() async {
try {
final response = await http.get(Uri.parse('$baseUrl/users'));
if (response.statusCode == 200) {
return json.decode(response.body);
} else {
throw Exception('Failed to load users: ${response.statusCode}');
}
} catch (e) {
throw Exception('Network error: $e');
}
}
/// 创建新用户
static Future<dynamic> createUser(String name, String email) async {
try {
final response = await http.post(
Uri.parse('$baseUrl/users'),
headers: {'Content-Type': 'application/json'},
body: json.encode({'name': name, 'email': email}),
);
if (response.statusCode == 201) {
return json.decode(response.body);
} else {
throw Exception('Failed to create user: ${response.statusCode}');
}
} catch (e) {
throw Exception('Network error: $e');
}
}
}
使用Dio(第三方HTTP客户端)
import 'package:dio/dio.dart';
class DioService {
static final Dio _dio = Dio();
/// 配置Dio拦截器
static void configureDio() {
_dio.options.baseUrl = 'https://api.example.com';
_dio.options.connectTimeout = Duration(seconds: 30);
_dio.options.receiveTimeout = Duration(seconds: 30);
// 添加拦截器
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
// 添加认证token
options.headers['Authorization'] = 'Bearer your_token';
return handler.next(options);
},
onError: (DioError e, handler) {
// 错误处理
return handler.next(e);
},
));
}
/// 获取数据
static Future<Response> getData(String endpoint) async {
try {
return await _dio.get(endpoint);
} on DioError catch (e) {
throw Exception('Dio error: ${e.message}');
}
}
}
4. 业务逻辑分离
服务层
/// 用户服务
class UserService {
final ApiService _apiService;
UserService(this._apiService);
/// 获取用户信息
Future<User> getUserById(int id) async {
final data = await _apiService.get('/users/$id');
return User.fromJson(data);
}
/// 更新用户信息
Future<void> updateUser(User user) async {
await _apiService.put('/users/${user.id}', user.toJson());
}
/// 删除用户
Future<void> deleteUser(int id) async {
await _apiService.delete('/users/$id');
}
}
数据模型
/// 用户数据模型
class User {
final int id;
final String name;
final String email;
final DateTime createdAt;
User({
required this.id,
required this.name,
required this.email,
required this.createdAt,
});
/// 从JSON创建User对象
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
createdAt: DateTime.parse(json['created_at']),
);
}
/// 将User对象转换为JSON
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
'created_at': createdAt.toIso8601String(),
};
}
}
三、完整示例:待办事项应用
UI部分
import 'package:flutter/material.dart';
class TodoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '待办事项',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: TodoListPage(),
);
}
}
class TodoListPage extends StatefulWidget {
@override
_TodoListPageState createState() => _TodoListPageState();
}
class _TodoListPageState extends State<TodoListPage> {
final List<TodoItem> _todos = [];
final TextEditingController _textController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('待办事项'),
actions: [
IconButton(
icon: Icon(Icons.delete_sweep),
onPressed: _clearCompleted,
),
],
),
body: Column(
children: [
// 添加新待办事项
Padding(
padding: EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _textController,
decoration: InputDecoration(
hintText: '输入新的待办事项',
border: OutlineInputBorder(),
),
),
),
SizedBox(width: 8),
ElevatedButton(
onPressed: _addTodo,
child: Text('添加'),
),
],
),
),
// 待办事项列表
Expanded(
child: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
final todo = _todos[index];
return Dismissible(
key: Key(todo.id),
onDismissed: (direction) {
_removeTodo(index);
},
background: Container(color: Colors.red),
child: ListTile(
leading: Checkbox(
value: todo.completed,
onChanged: (value) {
_toggleTodo(index);
},
),
title: Text(
todo.title,
style: todo.completed
? TextStyle(decoration: TextDecoration.lineThrough)
: null,
),
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () => _editTodo(index),
),
),
);
},
),
),
],
),
);
}
void _addTodo() {
if (_textController.text.isNotEmpty) {
setState(() {
_todos.add(TodoItem(
id: DateTime.now().millisecondsSinceEpoch.toString(),
title: _textController.text,
completed: false,
));
_textController.clear();
});
}
}
void _removeTodo(int index) {
setState(() {
_todos.removeAt(index);
});
}
void _toggleTodo(int index) {
setState(() {
_todos[index].completed = !_todos[index].completed;
});
}
void _editTodo(int index) {
showDialog(
context: context,
builder: (context) {
final controller = TextEditingController(text: _todos[index].title);
return AlertDialog(
title: Text('编辑待办事项'),
content: TextField(controller: controller),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('取消'),
),
TextButton(
onPressed: () {
setState(() {
_todos[index].title = controller.text;
});
Navigator.pop(context);
},
child: Text('保存'),
),
],
);
},
);
}
void _clearCompleted() {
setState(() {
_todos.removeWhere((todo) => todo.completed);
});
}
}
class TodoItem {
final String id;
String title;
bool completed;
TodoItem({
required this.id,
required this.title,
required this.completed,
});
}
后端逻辑部分
/// 待办事项服务
class TodoService {
final DatabaseHelper _databaseHelper;
TodoService(this._databaseHelper);
/// 获取所有待办事项
Future<List<TodoItem>> getTodos() async {
// 从数据库获取数据
final data = await _databaseHelper.getTodos();
return data.map((item) => TodoItem.fromJson(item)).toList();
}
/// 保存待办事项
Future<void> saveTodo(TodoItem todo) async {
await _databaseHelper.insertTodo(todo.toJson());
}
/// 删除待办事项
Future<void> deleteTodo(String id) async {
await _databaseHelper.deleteTodo(id);
}
/// 更新待办事项
Future<void> updateTodo(TodoItem todo) async {
await _databaseHelper.updateTodo(todo.toJson());
}
}
四、最佳实践
UI开发最佳实践
- 组件化:将UI拆分为可重用的组件
- 响应式设计:适配不同屏幕尺寸
- 一致性:保持设计风格统一
- 性能优化:避免不必要的重绘
代码逻辑最佳实践
- 分离关注点:UI、业务逻辑、数据层分离
- 错误处理:完善的异常处理机制
- 测试驱动:编写单元测试和集成测试
- 代码规范:遵循Dart代码规范
总结
Flutter开发需要同时关注UI设计和代码逻辑。UI方面要掌握Widget的使用、布局技巧和动画效果;代码逻辑方面要理解状态管理、数据持久化和网络请求等核心概念。通过合理的架构设计,可以开发出高性能、易维护的Flutter应用。

浙公网安备 33010602011771号