Flutter 完整开发指南 - 前端笔记-1. Flutter 基础 1.1 开发环境搭建 1.1.1 必要工具安装 Flutter SDK # Windo...

学习笔记

点滴记忆
回忆过往
首页>> web前端 >>Flutter 完整开发指南 - 前端笔记

1. Flutter 基础

1.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 
  2. 开发工具

    • Android Studio
    • VS Code
    • Xcode (仅 macOS)
  3. 环境检查

    flutter doctor 

1.1.2 IDE 配置

  1. VS Code 插件

    • Flutter
    • Dart
    • Flutter Widget Snippets
  2. Android Studio 插件

    • Flutter
    • Dart

1.1.3 创建项目

  1. 使用命令行创建
# 创建新项目 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 
  1. 使用 VS Code 创建
  • 打开 VS Code
  • 按下 Ctrl+Shift+P(Windows/Linux)或 Cmd+Shift+P(macOS)
  • 输入 Flutter: New Project
  • 选择项目存储位置
  • 输入项目名称(使用小写字母和下划线)
  • 等待项目创建和依赖安装完成
  1. 项目结构说明
my_app/
├── android/          # Android 平台相关代码
├── ios/             # iOS 平台相关代码
├── lib/             # Dart 源代码
│   └── main.dart    # 应用入口文件
├── test/            # 测试文件
├── web/             # Web 平台相关代码
├── pubspec.yaml     # 项目配置文件
└── README.md        # 项目说明文档 
  1. 运行项目
# 命令行运行 cd my_app
flutter run # VS Code 运行 # 1. 打开项目文件夹 # 2. 选择目标设备(模拟器或真机) # 3. 按 F5 或点击 "运行 > 启动调试" 
  1. 常用 VS Code 快捷操作
  • Ctrl + F5(Windows/Linux)或 Cmd + F5(macOS):无调试运行
  • Ctrl + Shift + F5:重新运行
  • Shift + Alt + F:格式化代码
  • Ctrl + .:快速修复/重构
  • Ctrl + Space:触发建议
  • Ctrl + Shift + R:重新加载
  1. 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<String> fruits = ['apple', 'banana', 'orange']; var numbers = <int>[1, 2, 3, 4, 5]; // Set(集合) Set<String> uniqueNames = {'John', 'Jane', 'Bob'}; // Map(字典) Map<String, int> 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<int> 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);  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,它们是用户界面的基本构建块。

  1. StatelessWidget
class GreetingWidget extends StatelessWidget { final String name; const GreetingWidget({ Key? key, required this.name, }) : super(key: key);  Widget build(BuildContext context) { return Text('Hello, $name!'); } } 
  1. StatefulWidget
class CounterWidget extends StatefulWidget {  _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { int _counter = 0; void _increment() { setState(() { _counter++; }); }  Widget build(BuildContext context) { return Column( children: [ Text('Count: $_counter'), ElevatedButton( onPressed: _increment, child: Text('Increment'), ), ], ); } } 

1.3.2 生命周期

class LifecycleWidget extends StatefulWidget {  _LifecycleWidgetState createState() => _LifecycleWidgetState(); } class _LifecycleWidgetState extends State<LifecycleWidget> {  void initState() { super.initState(); print('1. initState - 组件初始化'); }  void didChangeDependencies() { super.didChangeDependencies(); print('2. didChangeDependencies - 依赖变化'); }  void didUpdateWidget(LifecycleWidget oldWidget) { super.didUpdateWidget(oldWidget); print('3. didUpdateWidget - 组件更新'); }  void setState(VoidCallback fn) { super.setState(fn); print('4. setState - 状态更新'); }  void deactivate() { print('5. deactivate - 组件停用'); super.deactivate(); }  void dispose() { print('6. dispose - 组件销毁'); super.dispose(); }  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 {  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 {  Widget build(BuildContext context) { return Column( children: [ // 读取状态 Consumer<Counter>( builder: (context, counter, child) { return Text('Count: ${counter.count}'); }, ), // 修改状态 ElevatedButton( onPressed: () { context.read<Counter>().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());  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<List<Post>> 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<Post> 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<List<Post>> 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<void> init() async { _prefs = await SharedPreferences.getInstance(); } // 存储数据 static Future<bool> setString(String key, String value) async { return await _prefs.setString(key, value); } static Future<bool> 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<void> 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<Database> get database async { if (_database != null) return _database!; _database = await _initDB('app.db'); return _database!; } Future<Database> _initDB(String filePath) async { final dbPath = await getDatabasesPath(); final path = join(dbPath, filePath); return await openDatabase( path, version: 1, onCreate: _createDB, ); } Future<void> _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<int> insertUser(User user) async { final db = await database; return await db.insert('users', user.toMap()); } Future<User?> 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<List<User>> getAllUsers() async { final db = await database; final result = await db.query('users'); return result.map((map) => User.fromMap(map)).toList(); } Future<int> updateUser(User user) async { final db = await database; return await db.update( 'users', user.toMap(), where: 'id = ?', whereArgs: [user.id], ); } Future<int> 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. 内存优化
// 1. 使用 const 构造函数 const MyWidget({Key? key}) : super(key: key); // 2. 及时释放资源  void dispose() { _controller.dispose(); _focusNode.dispose(); super.dispose(); } // 3. 图片优化 Image.network( url, cacheWidth: 300, // 限制缓存大小 cacheHeight: 300, ) 
  1. 渲染优化
// 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), ); }, ) 
  1. 启动优化
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 进行开发。

记住,优秀的应用不仅要实现功能,还要注重性能优化、用户体验和代码质量。在实际开发中,要根据具体需求和场景选择合适的技术方案,并持续优化和改进。



×

感谢您的支持,我们会一直保持!

扫码支持
请土豪扫码随意打赏

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

打赏作者
版权所有,转载注意明处:前端笔记 » Flutter 完整开发指南

发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(0)