二、Flutter基础

目录

  • [1. 什么是Widget?Flutter中的Widget分为哪几类?](#1. 什么是Widget?Flutter中的Widget分为哪几类?)
  • [2. StatelessWidget和StatefulWidget的区别](#2. StatelessWidget和StatefulWidget的区别)
  • [3. StatefulWidget生命周期](#3. StatefulWidget生命周期)
  • [4. 什么是BuildContext?](#4. 什么是BuildContext?)
  • [5. 如何优化Widget重建?](#5. 如何优化Widget重建?)
  • [6. Flutter布局机制](#6. Flutter布局机制)
  • [7. Row/Column的主轴和交叉轴](#7. Row/Column的主轴和交叉轴)
  • [8. Expanded vs Flexible](#8. Expanded vs Flexible)
  • [9. Key的作用与使用场景](#9. Key的作用与使用场景)
  • [10. 国际化(i18n)实现](#10. 国际化(i18n)实现)

1. 什么是Widget?Flutter中的Widget分为哪几类?

Widget :Flutter应用的基础构建单元,描述UI元素的配置(如布局、样式等)。

  • 不可变性:Widget不可变,重建时生成新实例
  • 声明式UI:通过嵌套Widget树描述界面

主要分类

类别 特点 示例
StatelessWidget 无状态,属性不可变 Text , Icon , Container
StatefulWidget 有状态,可动态更新 Checkbox , TextField , Slider
InheritedWidget 数据共享,跨层级传递 Theme , MediaQuery
ProxyWidget 父Widget代理 ParentDataWidget
RenderObjectWidget 底层渲染控制 Opacity , Transform
dart 复制代码
// Widget树示例
Container( // 布局Widget
  padding: EdgeInsets.all(10),
  child: Column( // 布局Widget
    children: [
      Text('Hello', style: TextStyle(fontSize: 20)), // 无状态Widget
      StatefulCounter() // 有状态Widget
    ],
  ),
)

2. StatelessWidget和StatefulWidget的区别

特性 StatelessWidget StatefulWidget
状态管理 ❌ 无内部状态 ✅ 可维护可变状态
重建机制 完全重建 通过State 对象保留状态
生命周期 简单(仅build) 复杂(initState/didUpdateWidget等)
性能 更高 较低(需维护State)
使用场景 静态内容 交互式组件(表单/动画)

典型场景

  • Stateless:显示静态文本/图标
  • Stateful:计数器、开关按钮

3. StatefulWidget生命周期

是 否 createState initState didChangeDependencies build didUpdateWidget? deactivate dispose

关键方法

  1. initState:初始化状态(调用一次)
  2. didChangeDependencies:依赖变化时调用(如InheritedWidget更新)
  3. build:构建UI(必实现)
  4. didUpdateWidget:父Widget重建时触发
  5. setState:通知框架状态变化(触发rebuild)
  6. deactivate:从树中移除(可能重新插入)
  7. dispose:永久销毁,释放资源

⚠️ 注意 :避免在build()中做耗时操作!


4. 什么是BuildContext?

BuildContext 是Widget在树中位置的引用,核心作用:

查找祖先Widget

dart 复制代码
ThemeData theme = Theme.of(context); // 获取最近的Theme

导航操作

dart 复制代码
Navigator.push(context, MaterialPageRoute(...));

Widget状态管理

dart 复制代码
ScaffoldState scaffold = Scaffold.of(context);
scaffold.openDrawer(); // 打开抽屉

重要原则

  • 每个Widget有独立BuildContext
  • Context在Element创建时生成
  • 不可缓存Context(可能失效)

5. 如何优化Widget重建?

优化方案 实现方式 效果
const构造函数 const Text('Hello') 避免重复创建相同实例
拆分Widget树 将易变部分拆为子Widget 减少重建范围
使用StatelessWidget 优先用于静态内容 降低状态管理开销
Keys的正确使用 为列表项/状态Widget设置Key 精确控制更新
shouldRebuild @override bool updateShouldNotify 控制InheritedWidget更新范围

代码示例

dart 复制代码
// 优化前:整个Card重建
Widget build() {
  return Card(
    child: HeavyContent(), // 重组件
  );
}

// 优化后:仅变化部分重建
Widget build() {
  return const Card(  // const避免重建
    child: _HeavyContent(), // 拆分为独立Widget
  );
}

6. Flutter布局机制

布局流程(自顶向下):

  1. 父Widget传递约束(constraints: min/max宽高)
  2. 子Widget确定自身尺寸
  3. 父Widget定位子Widget(根据alignment/offset)

核心原则

  • 约束驱动:父给子约束,子不能超出约束
  • 递归布局:深度优先遍历Widget树
  • 单次布局:每帧最多布局一次
dart 复制代码
// 布局示例
ConstrainedBox(
  constraints: BoxConstraints(minWidth: 100, maxHeight: 200), // 父约束
  child: Container(
    width: 150,  // 子确定尺寸(在约束范围内)
    height: 180,
  ),
)

7. Row/Column的主轴和交叉轴

布局组件 主轴方向 交叉轴方向
Row 水平(X轴) 垂直(Y轴)
Column 垂直(Y轴) 水平(X轴)

主轴对齐mainAxisAlignment):

  • start/end/center/spaceBetween

交叉轴对齐crossAxisAlignment):

  • stretch/baseline/start
dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround, // 主轴均匀分布
  crossAxisAlignment: CrossAxisAlignment.center, // 交叉轴居中
  children: [ ... ],
)

8. Expanded vs Flexible

特性 Expanded Flexible
继承关系 Flexible的子类 基础类
flex默认值 flex=1 flex=1(可自定义)
空间占用 强制填满剩余空间 按需占用空间
fit行为 固定FlexFit.tight 可配置FlexFit.loose

使用场景

dart 复制代码
Row(
  children: [
    Container(width: 50), // 固定宽度
    Expanded( // 占满剩余宽度
      child: Text('Expanded Content'),
    ),
    Flexible( // 按内容宽度占用
      fit: FlexFit.loose,
      child: Text('Flexible'),
    )
  ],
)

9. Key的作用与使用场景

Key的作用

唯一标识Widget,帮助框架在重建时区分相同类型的Widget

使用场景

Key类型 适用场景
ValueKey 列表项(值唯一时)
ObjectKey 复杂对象的列表
UniqueKey 强制重建(如动画重置)
GlobalKey 跨组件访问状态

示例

dart 复制代码
ListView.builder(
  itemBuilder: (ctx, index) {
    return ListTile(
      key: ValueKey(items[index].id), // 基于id标识
      title: Text(items[index].name),
    );
  }
)

何时需要Key

  • 动态列表(增删改操作)
  • 保留状态(如表单输入框)
  • 需要跨组件访问状态

10. 国际化(i18n)实现

实现步骤

  1. 添加依赖
yaml 复制代码
dependencies:
  flutter_localizations:
    sdk: flutter
  intl: ^0.17.0
  1. 创建ARB文件**lib/l10n/app_en.arb**
json 复制代码
{
  "hello": "Hello!",
  "@hello": {"description": "欢迎语"}
}
  1. 生成本地化类
shell 复制代码
flutter gen-l10n
  1. 配置MaterialApp
dart 复制代码
MaterialApp(
  localizationsDelegates: AppLocalizations.localizationsDelegates,
  supportedLocales: AppLocalizations.supportedLocales,
)
  1. 使用翻译
dart 复制代码
Text(AppLocalizations.of(context)!.hello)