Flutter 完整开发指南

06-01 1842阅读

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)
    • 环境检查

      flutter doctor
      
1.1.2 IDE 配置
  1. VS Code 插件

    • Flutter
    • Dart
    • Flutter Widget Snippets
    • 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 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,它们是用户界面的基本构建块。

        1. 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!');
          }
        }
        
        1. 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. 内存优化
        // 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. 渲染优化
        // 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. 实战项目:新闻阅读器

        Flutter 完整开发指南

        Flutter 完整开发指南

        项目地址

        https://gitee.com/NextEraAbyss/flutter_forge

        结语

        本文档详细介绍了 Flutter 开发的各个方面,从基础知识到进阶技巧,并通过一个完整的新闻阅读器项目展示了 Flutter 的实际应用。希望这份文档能够帮助你更好地学习和使用 Flutter 进行开发。

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

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码