Flutter 笔记(上)

Flutter 笔记(上)

一、环境配置

1. 环境安装

Windows 安装步骤
  1. 下载 Flutter SDK

    • 访问 Flutter 官网
    • 下载稳定版 ZIP 文件
    • 解压到合适的位置(如 C:\src\flutter
  2. 配置环境变量

    • 打开系统环境变量设置
    • 在 Path 中添加:C:\src\flutter\bin
    • 重启命令行工具使环境变量生效
  3. 运行环境诊断

    flutter doctor
    
    • 检查所有依赖是否正确安装
    • 根据提示安装缺失的组件(如 Chrome、VS Code 等)
Mac 安装步骤
  1. 下载 Flutter SDK

    • 访问 Flutter 官网
    • 下载稳定版 ZIP 文件
    • 解压到合适位置(如 ~/development/flutter
  2. 配置环境变量

    • 编辑 ~/.zshrc~/.bash_profile
    • 添加:export PATH="$PATH:~/development/flutter/bin"
    • 运行 source ~/.zshrc 使配置生效
  3. 运行环境诊断

    flutter doctor
    

2. 创建 Flutter 项目

命令行创建项目
# 创建新项目
flutter create project_name

# 进入项目目录
cd project_name

# 启用 Web 支持(如果未启用)
flutter config --enable-web

# 运行项目(Web 平台)
flutter run -d chrome

# 或者指定其他浏览器
flutter run -d web-server
项目创建选项
# 创建带组织名称的项目
flutter create --org com.example project_name

# 创建使用特定语言的项目
flutter create --platforms=web project_name

二、项目结构详解

3. 应用目录结构

project_name/
├── .dart_tool/          # Dart 工具生成文件
├── .idea/               # IDE 配置文件
├── build/               # 构建输出目录
├── lib/                 # 源代码目录
│   └── main.dart       # 应用入口文件
├── test/                # 测试文件目录
├── web/                 # Web 平台资源
│   ├── index.html      # Web 入口 HTML
│   ├── favicon.png     # 网站图标
│   └── manifest.json   # Web 应用配置
├── .gitignore           # Git 忽略配置
├── .metadata            # Flutter 元数据
├── analysis_options.yaml # 代码分析配置
├── pubspec.yaml         # 依赖配置
├── pubspec.lock         # 依赖锁定文件
└── README.md            # 项目说明文档
核心目录详解
lib/ 目录

这是你编写 Dart 代码的主要位置

  • main.dart - 应用程序的入口文件,包含 main() 函数
  • 可以创建子文件夹组织代码:
    • lib/screens/ - 页面文件
    • lib/widgets/ - 自定义组件
    • lib/models/ - 数据模型
    • lib/utils/ - 工具函数
web/ 目录

Web 平台特定的文件

  • index.html - 网页的 HTML 模板
  • manifest.json - PWA(渐进式 Web 应用)配置
  • favicon.png - 网站图标
  • 可以在这里添加自定义的 CSS、JavaScript 等
test/ 目录

存放单元测试和组件测试代码

  • 测试文件命名格式:xxx_test.dart
重要配置文件
pubspec.yaml - 项目配置文件
name: project_name              # 项目名称
description: A new Flutter project.
version: 1.0.0+1                # 版本号

environment:
  sdk: '>=3.0.0 <4.0.0'         # Dart SDK 版本要求

dependencies:                    # 项目依赖
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2       # iOS 风格图标

dev_dependencies:                # 开发依赖
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true    # 启用 Material Design
  # assets:                     # 资源文件
  #   - images/
  #   - fonts/
pubspec.lock
  • 自动生成,记录依赖的具体版本
  • 不要手动修改
  • 确保团队成员使用相同版本的依赖
analysis_options.yaml

配置代码风格和静态分析规则

include: package:flutter_lints/flutter.yaml

linter:
  rules:
    - prefer_const_constructors
    - avoid_print
自动生成的文件(无需手动修改)
  • .dart_tool/ - Dart 分析工具的缓存
  • .idea/ - IntelliJ IDEA / Android Studio 的配置
  • build/ - 编译后的文件,运行 flutter clean 可删除
  • .metadata - Flutter 项目的元信息
  • flutter_core.iml - IntelliJ 的模块配置文件

三、核心概念

4. 应用启动与 Widget

main() 函数与 runApp()

应用启动流程:

void main() {
  runApp(const MyApp());
}

详细说明:

  1. main() 函数

    • Dart 程序的唯一入口点
    • 程序从这里开始执行
    • 必须是顶级函数(不在类中)
    • 返回类型为 void
  2. runApp(Widget app) 函数

    • Flutter 框架提供的启动函数
    • 将传入的 Widget 设为根组件
    • 创建 Widget 树并渲染到屏幕
    • 初始化 Flutter 的渲染引擎
    • 绑定到原生平台

扩展用法:

void main() {
  // 初始化 Flutter 绑定
  WidgetsFlutterBinding.ensureInitialized();
  
  // 可以在这里做一些初始化工作
  // 例如:设置屏幕方向、加载配置等
  
  runApp(const MyApp());
}

Widget 的核心概念

什么是 Widget?

Widget 是 Flutter 中最核心的概念,可以理解为"组件"或"小部件"。

核心特性:

  • 一切皆 Widget - Flutter 中所有的 UI 元素都是 Widget
  • 不可变性(Immutable) - Widget 对象一旦创建就不能修改
  • 声明式 - 描述 UI 应该"是什么",而不是"怎么做"
  • 轻量级 - Widget 只是配置信息,创建和销毁成本很低

Widget 树的概念:

MaterialApp
  └─ Scaffold
      ├─ AppBar
      │   └─ Text
      └─ Center
          └─ Column
              ├─ Text
              └─ ElevatedButton
                  └─ Text

Flutter 通过嵌套 Widget 构建 UI,形成树状结构。

三棵树的关系:

  1. Widget 树 - 配置信息(轻量、不可变)
  2. Element 树 - Widget 的实例,管理 Widget 生命周期
  3. RenderObject 树 - 实际的渲染对象(重量级)

提示:当 UI 需要更新时,Flutter 只重建 Widget 树,通过对比来更新 Element 树和 RenderObject 树。


StatelessWidget(无状态组件)

定义:
无状态组件是不需要维护状态的组件,一旦创建后其属性就不会改变。

使用场景:

  • 展示静态内容(如文本、图标)
  • 不需要用户交互的 UI
  • 只依赖传入参数的组件

创建方式:

class MyWidget extends StatelessWidget {
  // 1. 构造函数(可选参数)
  const MyWidget({super.key});

  // 2. build 方法(必须实现)
  
  Widget build(BuildContext context) {
    return Container(
      child: Text('Hello Flutter'),
    );
  }
}

带参数的无状态组件:

class GreetingWidget extends StatelessWidget {
  // 定义属性(必须是 final)
  final String name;
  final int age;

  // 构造函数
  const GreetingWidget({
    super.key,
    required this.name,
    required this.age,
  });

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('你好,$name'),
        Text('年龄:$age 岁'),
      ],
    );
  }
}

// 使用
GreetingWidget(name: '张三', age: 18)

关键点:

  • 所有属性必须是 final
  • 构造函数使用 const 可以提高性能
  • 只有一个 build() 方法
  • build() 方法每次都返回新的 Widget 树

StatefulWidget(有状态组件)

定义:
有状态组件可以在运行时改变其状态,状态改变时 UI 会自动更新。

使用场景:

  • 需要用户交互(按钮点击、输入等)
  • 需要根据时间或网络请求更新 UI
  • 需要动画效果
  • 表单、计数器、复选框等

创建方式:

StatefulWidget 需要创建两个类:

// 1. StatefulWidget 类(不可变)
class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

  // 创建 State 对象
  
  State<CounterWidget> createState() => _CounterWidgetState();
}

// 2. State 类(可变)
class _CounterWidgetState extends State<CounterWidget> {
  // 定义状态变量(可以修改)
  int _counter = 0;

  // 定义方法来修改状态
  void _incrementCounter() {
    setState(() {
      // setState 会触发 build 方法重新执行
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('计数:$_counter'),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('点击 +1'),
        ),
      ],
    );
  }
}

完整示例(带参数的有状态组件):

class TodoItem extends StatefulWidget {
  final String title;  // Widget 的属性(不可变)

  const TodoItem({super.key, required this.title});

  
  State<TodoItem> createState() => _TodoItemState();
}

class _TodoItemState extends State<TodoItem> {
  bool _isCompleted = false;  // State 的属性(可变)

  void _toggleComplete() {
    setState(() {
      _isCompleted = !_isCompleted;
    });
  }

  
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
        widget.title,  // 通过 widget 访问 StatefulWidget 的属性
        style: TextStyle(
          decoration: _isCompleted 
            ? TextDecoration.lineThrough 
            : null,
        ),
      ),
      trailing: Checkbox(
        value: _isCompleted,
        onChanged: (value) => _toggleComplete(),
      ),
    );
  }
}

关键点:

  • StatefulWidget 类本身是不可变的
  • State 类持有可变的状态
  • 使用 setState() 来更新状态和 UI
  • 通过 widget.属性名 访问 StatefulWidget 的属性
  • State 类名通常以下划线开头(私有)

setState() 详解

作用:
通知 Flutter 框架状态已改变,需要重新构建 UI。

用法:

setState(() {
  // 在这里修改状态变量
  _counter++;
  _isVisible = !_isVisible;
});

重要原则:

  • 只能在 State 对象中调用
  • 必须在回调函数中修改状态
  • 调用后会触发 build() 方法
  • 不要在 build() 方法中调用 setState()

错误示例:

// 错误:直接修改,不会更新 UI
_counter++;

// 错误:在 setState 外部修改
_counter++;
setState(() {});

// 错误:在 build 中调用(会导致无限循环)

Widget build(BuildContext context) {
  setState(() {  // 不要这样做
    _counter++;
  });
  return Text('$_counter');
}

正确示例:

void _updateCounter() {
  setState(() {
    _counter++;  // 在 setState 中修改
  });
}

BuildContext 详解

定义:
BuildContext 是 Widget 在 Widget 树中位置的句柄。

作用:

  • 定位 Widget 在树中的位置
  • 向上查找父级 Widget
  • 访问主题、导航器等全局信息

常见用法:

  1. 获取主题数据

Widget build(BuildContext context) {
  // 获取当前主题
  final theme = Theme.of(context);
  
  return Text(
    'Hello',
    style: TextStyle(color: theme.primaryColor),
  );
}
  1. 获取屏幕尺寸

Widget build(BuildContext context) {
  final screenSize = MediaQuery.of(context).size;
  final screenWidth = screenSize.width;
  final screenHeight = screenSize.height;
  
  return Container(
    width: screenWidth * 0.8,
    height: screenHeight * 0.5,
  );
}
  1. 导航到新页面
void _navigateToNextPage(BuildContext context) {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => NextPage()),
  );
}
  1. 显示 SnackBar
void _showMessage(BuildContext context) {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('操作成功')),
  );
}

注意事项:

  • 每个 Widget 的 build() 方法都会接收一个 context 参数
  • 不要在异步操作后使用过期的 context
  • 某些方法(如 Navigator.of(context))需要特定的父级 Widget

生命周期方法

定义:
StatefulWidget 的 State 对象在其生命周期中会调用一系列方法,了解这些方法有助于在合适的时机执行操作。

完整生命周期流程:

class LifecycleDemo extends StatefulWidget {
  const LifecycleDemo({super.key});

  
  State<LifecycleDemo> createState() => _LifecycleDemoState();
}

class _LifecycleDemoState extends State<LifecycleDemo> {
  
  // 1. 构造函数(最先执行)
  _LifecycleDemoState() {
    print('1. 构造函数');
  }
  
  // 2. initState(初始化状态,只执行一次)
  
  void initState() {
    super.initState();
    print('2. initState - 初始化数据、订阅、启动动画');
    // 适合做:初始化数据、订阅Stream、启动定时器、网络请求
  }
  
  // 3. didChangeDependencies(依赖变化时调用)
  
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('3. didChangeDependencies - InheritedWidget 变化');
    // 适合做:依赖InheritedWidget的数据变化处理
  }
  
  // 4. build(构建UI,会多次执行)
  
  Widget build(BuildContext context) {
    print('4. build - 构建UI');
    return Container(child: Text('生命周期演示'));
  }
  
  // 5. didUpdateWidget(Widget配置更新时调用)
  
  void didUpdateWidget(LifecycleDemo oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('5. didUpdateWidget - Widget重新配置');
    // 适合做:比较新旧Widget,根据变化更新状态
  }
  
  // 6. setState(触发重新构建)
  void _updateState() {
    setState(() {
      print('6. setState - 触发rebuild');
    });
  }
  
  // 7. deactivate(Widget从树中移除时调用)
  
  void deactivate() {
    print('7. deactivate - 从树中移除');
    super.deactivate();
  }
  
  // 8. dispose(销毁时调用,只执行一次)
  
  void dispose() {
    print('8. dispose - 清理资源');
    // 适合做:取消订阅、释放资源、停止动画、关闭Stream
    super.dispose();
  }
}

常用生命周期方法:

1. initState()

  • 在 State 对象被插入树时调用(只执行一次)
  • 适合初始化数据、订阅、启动动画

void initState() {
  super.initState();
  _controller = AnimationController(vsync: this);
  _loadData();
}

2. dispose()

  • 在 State 对象被永久移除时调用(只执行一次)
  • 必须清理资源,避免内存泄漏

void dispose() {
  _controller.dispose();
  _subscription.cancel();
  super.dispose();
}

3. didChangeDependencies()

  • 依赖的 InheritedWidget 变化时调用
  • initState 后会立即调用一次

void didChangeDependencies() {
  super.didChangeDependencies();
  final theme = Theme.of(context);
  // 使用主题数据
}

实际应用示例:

class TimerWidget extends StatefulWidget {
  
  _TimerWidgetState createState() => _TimerWidgetState();
}

class _TimerWidgetState extends State<TimerWidget> {
  Timer? _timer;
  int _counter = 0;

  
  void initState() {
    super.initState();
    // 启动定时器
    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      setState(() {
        _counter++;
      });
    });
  }

  
  void dispose() {
    // 停止定时器,释放资源
    _timer?.cancel();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Text('计时:$_counter 秒');
  }
}

Material 库

Flutter 的 UI 库:

Flutter 提供了两套完整的 UI 组件库:

  1. Material Design - Google 的设计语言(Android 风格)

    • 现代、扁平化设计
    • 适用于 Android、Web、桌面应用
  2. Cupertino - Apple 的设计语言(iOS 风格)

    • 适用于 iOS 和 macOS 应用

导入 Material 库:

import 'package:flutter/material.dart';

基础应用结构:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

// 根组件
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      // 应用标题
      title: 'Flutter Demo',
      
      // 主题配置
      theme: ThemeData(
        primarySwatch: Colors.blue,
        brightness: Brightness.light,
      ),
      
      // 暗色主题
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      
      // 首页
      home: const HomePage(),
      
      // 是否显示调试标签
      debugShowCheckedModeBanner: false,
    );
  }
}

// 首页
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('首页'),
      ),
      body: const Center(
        child: Text('Hello Flutter'),
      ),
    );
  }
}

MaterialApp 常用属性:

  • title - 应用标题(在任务管理器中显示)
  • theme - 亮色主题
  • darkTheme - 暗色主题
  • home - 首页 Widget
  • routes - 路由表(页面导航)
  • initialRoute - 初始路由
  • debugShowCheckedModeBanner - 是否显示 DEBUG 标签

常用的 Material 组件:

  • Scaffold - 页面脚手架
  • AppBar - 顶部导航栏
  • FloatingActionButton - 悬浮按钮
  • Drawer - 抽屉菜单
  • BottomNavigationBar - 底部导航栏
  • Card - 卡片
  • Dialog - 对话框
  • SnackBar - 底部提示条
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值