Flutter 完整开发指南
1. Flutter 基础
1.1 开发环境搭建
1.1.1 必要工具安装
-
Flutter SDK
# Windows # 1. 下载 Flutter SDK # 2. 解压到合适的目录,如 C:\flutter # 3. 添加 flutter\bin 到环境变量 Path # macOS brew install flutter # Linux sudo snap install flutter --classic
-
开发工具
- Android Studio
- VS Code
- Xcode (仅 macOS)
-
环境检查
flutter doctor
1.1.2 IDE 配置
-
VS Code 插件
- Flutter
- Dart
- Flutter Widget Snippets
-
Android Studio 插件
- Flutter
- Dart
1.1.3 创建项目
- 使用命令行创建
# 创建新项目 flutter create my_app # 指定组织名称 flutter create --org com.example my_app # 指定使用特定平台 flutter create --platforms android,ios my_app # 创建包含示例代码的项目 flutter create --sample=material.AppBar.1 my_app
- 使用 VS Code 创建
- 打开 VS Code
- 按下 Ctrl+Shift+P(Windows/Linux)或 Cmd+Shift+P(macOS)
- 输入 Flutter: New Project
- 选择项目存储位置
- 输入项目名称(使用小写字母和下划线)
- 等待项目创建和依赖安装完成
- 项目结构说明
my_app/ ├── android/ # Android 平台相关代码 ├── ios/ # iOS 平台相关代码 ├── lib/ # Dart 源代码 │ └── main.dart # 应用入口文件 ├── test/ # 测试文件 ├── web/ # Web 平台相关代码 ├── pubspec.yaml # 项目配置文件 └── README.md # 项目说明文档
- 运行项目
# 命令行运行 cd my_app flutter run # VS Code 运行 # 1. 打开项目文件夹 # 2. 选择目标设备(模拟器或真机) # 3. 按 F5 或点击 "运行 > 启动调试"
- 常用 VS Code 快捷操作
- Ctrl + F5(Windows/Linux)或 Cmd + F5(macOS):无调试运行
- Ctrl + Shift + F5:重新运行
- Shift + Alt + F:格式化代码
- Ctrl + .:快速修复/重构
- Ctrl + Space:触发建议
- Ctrl + Shift + R:重新加载
- VS Code 常用插件推荐
- Flutter
- Dart
- Flutter Widget Snippets
- Awesome Flutter Snippets
- Flutter Tree
- pubspec Assist
- Error Lens
1.2 Dart 语言基础
1.2.1 变量与数据类型
// 变量声明 var name = 'Bob'; // 类型推断 String name = 'Bob'; // 显式声明 dynamic name = 'Bob'; // 动态类型 final name = 'Bob'; // 运行时常量 const pi = 3.14; // 编译时常量 // 内置数据类型 int age = 30; // 整数 double height = 1.75; // 浮点数 String name = 'Bob'; // 字符串 bool isStudent = true; // 布尔值
1.2.2 集合类型
// List(列表) List fruits = ['apple', 'banana', 'orange']; var numbers = [1, 2, 3, 4, 5]; // Set(集合) Set uniqueNames = {'John', 'Jane', 'Bob'}; // Map(字典) Map scores = { 'math': 95, 'english': 85, 'history': 90, };
1.2.3 函数
// 基本函数 int add(int a, int b) { return a + b; } // 箭头函数 int multiply(int a, int b) => a * b; // 可选参数 String greet(String name, [String? title]) { return title != null ? '$title $name' : 'Hello $name'; } // 命名参数 void printPerson({ required String name, int? age, String? address, }) { print('Name: $name, Age: ${age ?? "Unknown"}, Address: ${address ?? "N/A"}'); } // 函数作为参数 void processNumbers(List numbers, int Function(int) processor) { for (var number in numbers) { print(processor(number)); } }
1.2.4 类与对象
class Person { // 属性 final String name; int age; // 构造函数 Person(this.name, this.age); // 命名构造函数 Person.guest() : name = 'Guest', age = 0; // 方法 void introduce() { print('My name is $name and I am $age years old.'); } // Getter String get info => '$name ($age)'; // Setter set setAge(int value) { if (value >= 0) { age = value; } } } // 继承 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 Musical { void playMusic() { print('Playing music...'); } } class MusicStudent extends Student with Musical { MusicStudent(String name, int age, String school) : super(name, age, school); }
1.3 Flutter 核心概念
1.3.1 Widget
Flutter 中一切都是 Widget,它们是用户界面的基本构建块。
- StatelessWidget
class GreetingWidget extends StatelessWidget { final String name; const GreetingWidget({ Key? key, required this.name, }) : super(key: key); @override Widget build(BuildContext context) { return Text('Hello, $name!'); } }
- StatefulWidget
class CounterWidget extends StatefulWidget { @override _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State { int _counter = 0; void _increment() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Column( children: [ Text('Count: $_counter'), ElevatedButton( onPressed: _increment, child: Text('Increment'), ), ], ); } }
1.3.2 生命周期
class LifecycleWidget extends StatefulWidget { @override _LifecycleWidgetState createState() => _LifecycleWidgetState(); } class _LifecycleWidgetState extends State { @override void initState() { super.initState(); print('1. initState - 组件初始化'); } @override void didChangeDependencies() { super.didChangeDependencies(); print('2. didChangeDependencies - 依赖变化'); } @override void didUpdateWidget(LifecycleWidget oldWidget) { super.didUpdateWidget(oldWidget); print('3. didUpdateWidget - 组件更新'); } @override void setState(VoidCallback fn) { super.setState(fn); print('4. setState - 状态更新'); } @override void deactivate() { print('5. deactivate - 组件停用'); super.deactivate(); } @override void dispose() { print('6. dispose - 组件销毁'); super.dispose(); } @override Widget build(BuildContext context) { print('7. build - 构建UI'); return Container(); } }
1.4 常用组件
1.4.1 基础组件
// 文本组件 Text( 'Hello World', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.blue, ), ) // 图片组件 Image.network('https://example.com/image.jpg') Image.asset('assets/images/logo.png') // 按钮组件 ElevatedButton( onPressed: () {}, child: Text('点击我'), ) TextButton( onPressed: () {}, child: Text('文本按钮'), ) IconButton( icon: Icon(Icons.add), onPressed: () {}, ) // 输入框组件 TextField( decoration: InputDecoration( labelText: '用户名', hintText: '请输入用户名', border: OutlineInputBorder(), ), onChanged: (value) { print('输入内容: $value'); }, )
1.4.2 布局组件
// Container - 容器组件 Container( width: 200, height: 200, padding: EdgeInsets.all(16), margin: EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black26, offset: Offset(0, 2), blurRadius: 6, ), ], ), child: Text('容器内容'), ) // Row - 水平布局 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('左侧'), Text('中间'), Text('右侧'), ], ) // Column - 垂直布局 Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('顶部'), Text('中部'), Text('底部'), ], ) // Stack - 层叠布局 Stack( children: [ Image.asset('background.jpg'), Positioned( bottom: 16, right: 16, child: Text('覆盖文本'), ), ], ) // Expanded & Flexible - 弹性布局 Row( children: [ Expanded( flex: 2, child: Container(color: Colors.red), ), Flexible( flex: 1, child: Container(color: Colors.blue), ), ], )
1.5 布局与导航
1.5.1 基本页面布局
Scaffold( appBar: AppBar( title: Text('应用标题'), actions: [ IconButton( icon: Icon(Icons.settings), onPressed: () {}, ), ], ), body: Center( child: Text('页面内容'), ), floatingActionButton: FloatingActionButton( onPressed: () {}, child: Icon(Icons.add), ), drawer: Drawer( child: ListView( children: [ DrawerHeader( child: Text('侧边栏头部'), decoration: BoxDecoration( color: Colors.blue, ), ), ListTile( title: Text('菜单项 1'), onTap: () {}, ), ], ), ), )
1.5.2 导航
// 基本导航 Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(), ), ); // 带参数导航 Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(id: 123), ), ); // 命名路由配置 MaterialApp( initialRoute: '/', routes: { '/': (context) => HomeScreen(), '/detail': (context) => DetailScreen(), '/settings': (context) => SettingsScreen(), }, ) // 使用命名路由 Navigator.pushNamed( context, '/detail', arguments: {'id': 123}, ); // 获取路由参数 class DetailScreen extends StatelessWidget { @override Widget build(BuildContext context) { final args = ModalRoute.of(context)!.settings.arguments as Map; return Scaffold( body: Center( child: Text('详情页 ID: ${args['id']}'), ), ); } }
2. Flutter 进阶
2.1 状态管理
2.1.1 Provider
// 1. 定义数据模型 class Counter with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } // 2. 提供状态 void main() { runApp( ChangeNotifierProvider( create: (context) => Counter(), child: MyApp(), ), ); } // 3. 使用状态 class CounterWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ // 读取状态 Consumer( builder: (context, counter, child) { return Text('Count: ${counter.count}'); }, ), // 修改状态 ElevatedButton( onPressed: () { context.read().increment(); }, child: Text('增加'), ), ], ); } }
2.1.2 GetX
// 1. 定义控制器 class CounterController extends GetxController { var count = 0.obs; void increment() => count++; } // 2. 使用控制器 class CounterPage extends StatelessWidget { final controller = Get.put(CounterController()); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( children: [ // 自动更新UI Obx(() => Text('Count: ${controller.count}')), ElevatedButton( onPressed: controller.increment, child: Text('增加'), ), ], ), ), ); } }
2.2 网络请求
2.2.1 Dio 网络请求
class ApiService { final Dio _dio = Dio(); ApiService() { _dio.options.baseUrl = 'https://api.example.com'; _dio.options.connectTimeout = 5000; _dio.options.receiveTimeout = 3000; // 添加拦截器 _dio.interceptors.add(InterceptorsWrapper( onRequest: (options, handler) { // 请求前处理 options.headers['Authorization'] = 'Bearer token'; return handler.next(options); }, onResponse: (response, handler) { // 响应处理 return handler.next(response); }, onError: (DioError e, handler) { // 错误处理 return handler.next(e); }, )); } // GET 请求 Future getPosts() async { try { final response = await _dio.get('/posts'); return (response.data as List) .map((json) => Post.fromJson(json)) .toList(); } catch (e) { throw Exception('Failed to load posts'); } } // POST 请求 Future createPost(Post post) async { try { final response = await _dio.post( '/posts', data: post.toJson(), ); return Post.fromJson(response.data); } catch (e) { throw Exception('Failed to create post'); } } }
2.2.2 GraphQL 请求
// 1. 定义查询 const String getPostsQuery = r''' query GetPosts { posts { id title content author { name } } } '''; // 2. 实现 GraphQL 客户端 class GraphQLService { late GraphQLClient _client; GraphQLService() { final HttpLink httpLink = HttpLink('https://api.example.com/graphql'); _client = GraphQLClient( link: httpLink, cache: GraphQLCache(), ); } Future getPosts() async { try { final QueryResult result = await _client.query( QueryOptions( document: gql(getPostsQuery), ), ); if (result.hasException) { throw result.exception!; } return (result.data!['posts'] as List) .map((json) => Post.fromJson(json)) .toList(); } catch (e) { throw Exception('Failed to fetch posts: $e'); } } }
2.3 数据持久化
2.3.1 SharedPreferences
class PreferencesService { static late SharedPreferences _prefs; static Future init() async { _prefs = await SharedPreferences.getInstance(); } // 存储数据 static Future setString(String key, String value) async { return await _prefs.setString(key, value); } static Future setInt(String key, int value) async { return await _prefs.setInt(key, value); } // 读取数据 static String? getString(String key) { return _prefs.getString(key); } static int? getInt(String key) { return _prefs.getInt(key); } // 示例使用 static Future saveUserInfo(User user) async { await setString('username', user.name); await setInt('age', user.age); } static User? getUserInfo() { final name = getString('username'); final age = getInt('age'); if (name != null && age != null) { return User(name: name, age: age); } return null; } }
2.3.2 SQLite 数据库
class DatabaseHelper { static final DatabaseHelper instance = DatabaseHelper._init(); static Database? _database; DatabaseHelper._init(); Future get database async { if (_database != null) return _database!; _database = await _initDB('app.db'); return _database!; } Future _initDB(String filePath) async { final dbPath = await getDatabasesPath(); final path = join(dbPath, filePath); return await openDatabase( path, version: 1, onCreate: _createDB, ); } Future _createDB(Database db, int version) async { // 创建用户表 await db.execute(''' CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE NOT NULL, created_at TEXT NOT NULL ) '''); // 创建文章表 await db.execute(''' CREATE TABLE articles ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, user_id INTEGER, created_at TEXT NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id) ) '''); } // CRUD 操作 Future insertUser(User user) async { final db = await database; return await db.insert('users', user.toMap()); } Future getUser(int id) async { final db = await database; final maps = await db.query( 'users', where: 'id = ?', whereArgs: [id], ); if (maps.isNotEmpty) { return User.fromMap(maps.first); } return null; } Future getAllUsers() async { final db = await database; final result = await db.query('users'); return result.map((map) => User.fromMap(map)).toList(); } Future updateUser(User user) async { final db = await database; return await db.update( 'users', user.toMap(), where: 'id = ?', whereArgs: [user.id], ); } Future deleteUser(int id) async { final db = await database; return await db.delete( 'users', where: 'id = ?', whereArgs: [id], ); } }
2.4 打包与优化
2.4.1 打包配置
# android/app/build.gradle android { defaultConfig { applicationId "com.example.myapp" minSdkVersion 16 targetSdkVersion 30 versionCode 1 versionName "1.0.0" } signingConfigs { release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
2.4.2 性能优化
- 内存优化
// 1. 使用 const 构造函数 const MyWidget({Key? key}) : super(key: key); // 2. 及时释放资源 @override void dispose() { _controller.dispose(); _focusNode.dispose(); super.dispose(); } // 3. 图片优化 Image.network( url, cacheWidth: 300, // 限制缓存大小 cacheHeight: 300, )
- 渲染优化
// 1. 使用 RepaintBoundary 隔离重绘区域 RepaintBoundary( child: MyComplexWidget(), ) // 2. 优化列表性能 ListView.builder( itemCount: items.length, cacheExtent: 100.0, // 预加载区域 itemBuilder: (context, index) { return ListTile( key: ValueKey(items[index].id), // 使用唯一key title: Text(items[index].title), ); }, )
- 启动优化
void main() async { // 1. 延迟初始化 WidgetsFlutterBinding.ensureInitialized(); // 2. 预加载资源 await precacheImage( AssetImage('assets/images/splash.png'), null, ); // 3. 并行初始化 await Future.wait([ SharedPreferences.getInstance(), DatabaseHelper.instance.initDatabase(), loadConfigurations(), ]); runApp(MyApp()); }
3. 实战项目:新闻阅读器
项目地址
https://gitee.com/NextEraAbyss/flutter_forge
结语
本文档详细介绍了 Flutter 开发的各个方面,从基础知识到进阶技巧,并通过一个完整的新闻阅读器项目展示了 Flutter 的实际应用。希望这份文档能够帮助你更好地学习和使用 Flutter 进行开发。
记住,优秀的应用不仅要实现功能,还要注重性能优化、用户体验和代码质量。在实际开发中,要根据具体需求和场景选择合适的技术方案,并持续优化和改进。
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。