当前位置: 首页 > article >正文

Flutter 完整开发指南

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)
    • Appuploader (iOS 开发助手,用于简化 iOS 应用的打包和上传流程)
  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
    
  2. 使用 VS Code 创建

    • 打开 VS Code
    • 按下 Ctrl+Shift+P(Windows/Linux)或 Cmd+Shift+P(macOS)
    • 输入 Flutter: New Project
    • 选择项目存储位置
    • 输入项目名称(使用小写字母和下划线)
    • 等待项目创建和依赖安装完成
  3. 项目结构说明

    my_app/
    ├── android/          # Android 平台相关代码
    ├── ios/             # iOS 平台相关代码
    ├── lib/             # Dart 源代码
    │   └── main.dart    # 应用入口文件
    ├── test/            # 测试文件
    ├── web/             # Web 平台相关代码
    ├── pubspec.yaml     # 项目配置文件
    └── README.md        # 项目说明文档
    
  4. 运行项目

    # 命令行运行
    cd my_app
    flutter run
    
    # VS Code 运行
    # 1. 打开项目文件夹
    # 2. 选择目标设备(模拟器或真机)
    # 3. 按 F5 或点击 "运行 > 启动调试"
    
  5. 常用 VS Code 快捷操作

    • Ctrl + F5(Windows/Linux)或 Cmd + F5(macOS):无调试运行
    • Ctrl + Shift + F5:重新运行
    • Shift + Alt + F:格式化代码
    • Ctrl + .:快速修复/重构
    • Ctrl + Space:触发建议
    • Ctrl + Shift + R:重新加载
  6. 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!');
      }
    }
    
  2. 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']}'),
      ),
    );
  }
}

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

http://www.kler.cn/a/611832.html

相关文章:

  • 系统调用 与 中断
  • Transformer | 一文了解:缩放、批量、多头、掩码、交叉注意力机制(Attention)
  • DMA 之FIFO的作用
  • .NET开源的智能体相关项目推荐
  • c#的反射和特性
  • Docker实现MySQL主从复制配置【简易版】
  • 旅游纵览杂志旅游纵览杂志社旅游纵览编辑部2025年第2期目录
  • 微服务与分布式系统
  • Axure设计之中继器表格——拖动列调整位置教程(中继器)
  • python文件保存
  • Nextjs15 - 服务端组件(RSC)与客服端组件
  • SVTAV1热点函数-svt_ext_all_sad_calculation_8x8_16x16_avx2
  • python面试-基础
  • thinkphp8.0\swoole的websocket应用
  • vue配置.eslintrc、.prettierrc详解
  • Android 问真八字-v2.1.7[看八字APP]
  • Netty源码—8.编解码原理二
  • 2025年具有AI招聘管理系统选型及攻略分享
  • Rust从入门到精通之入门篇:8.基本数据结构
  • 快速入手-基于Django-rest-framework的mixins混合类(五)