[译] Flutter 核心概念详解: Widget、State、Context 及 InheritedWidget

本文详细介绍了Flutter开发中的关键概念:Widget、State和Context。阐述了Stateless和Stateful Widget的区别,State与Context的关系,以及如何在Widget之间进行交互,特别是InheritedWidget的作用和用法。此外,还探讨了Widget的生命周期,包括初始化、构建和销毁等阶段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文涵盖了 Flutter 应用中有关 Widget、State、Context 及 InheritedWidget 的重要概念。因为 InheritedWidget 是最重要且文档缺乏的部件之一,故需特别关注。

难度:初学者

前言

Flutter 中的 WidgetStateContext 是每个 Flutter 开发者都需要充分理解的最重要的概念之一。

虽然存在大量文档,但并没有一个能够清晰地解释它。

我将用自己的语言来解释这些概念,知道这些可能会让一些纯理论者感到不安,但本文的真正目的是试图说清以下主题:

  • Stateful Widget 和 Stateless Widget 的区别
  • Context 是什么
  • State 是什么并且如何使用它
  • context 与其 state 对象之间的关系
  • InheritedWidget 及在 Widgets 树中传播信息的方式
  • 重建的概念

本文同时发布于 Medium - Flutter Community

第一部分:概念

Widget 的概念

Flutter 中,几乎所有的东西都是 Widget

将一个 Widget 想象为一个可视化组件(或与应用可视化方面交互的组件)。

当你需要构建与布局直接或间接相关的任何内容时,你正在使用 Widget

Widget 树的概念

Widget 以树结构进行组织。

包含其他 Widget 的 Widget 被称为父 Widget(或Widget 容器)。包含在父 Widget 中的 Widget 被称为子 Widget

让我们用 Flutter 自动生成的基础应用来说明这一点。以下是简化代码,仅有 build 方法:

@override
Widget build(BuildContext){
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),
    );
}
复制代码

如果我们现在观察这个基本示例,我们将获得以下 Widget 树结构(限制代码中存在的 Widget 列表):

Context 的概念

另外一个重要的概念是 Context

Context 仅仅是已创建的所有 Widget 树结构中某个 Widget 的位置引用。

简而言之,将 context 作为 Widget 树的一部分,其中 context 所对应的 Widget 被添加到此树中。

一个 context 仅仅从属于一个 widget。

如果 widget ‘A’ 拥有子 widget,那么 widget ‘A’ 的 context 将成为其直接关联子 context父 context

读到这里会很明显发现 context 是链接在一起的,并且会形成一个 context 树(父子关系)。

如果我们现在尝试在上图中说明 Context 的概念,我们得到(依旧是一个非常简化的视图)每种颜色代表一个 context除了 MyApp,它是不同的):

Context 可见性 (简短描述):

某些东西 只能在自己的 context 或在其父 context 中可见。

通过上述描述我们可以将其从子 context 中提取出来,它很容易找到一个 祖先(= 父)Widget。

一个例子,考虑 Scaffold > Center > Column > Text:context.ancestorWidgetOfExactType(Scaffold) => 通过从 Text 的 context 得到树结构来返回第一个 Scaffold。

从父 context 中,也可以找到 后代(= 子)Widget,但不建议这样做(我们将稍后讨论)。

Widget 的类型

Widget 拥有 2 种类型:

Stateless Widget

这些可视化组件除了它们自身的配置信息外不依赖于任何其他信息,该信息在其直接父节点构建时提供。

换句话说,这些 Widget 一旦创建就不关心任何变化

这样的 Widget 称为 Stateless Widget

这种 Widget 的典型示例可以是 Text、Row、Column 和 Container 等。在构建时,我们只需将一些参数传递给它们。

参数可以是装饰、尺寸、甚至其他 widget 中的任何内容。需要强调的是,该配置一旦被创建,在下次构建过程之前都不会改变。

stateless widget 只有在 loaded/built 时才会绘制一次,这意味着任何事件或用户操作都无法对该 Widget 进行重绘。

Stateless Widget 生命周期

以下是与 Stateless Widget 相关的典型代码结构。

如下所示,我们可以将一些额外的参数传递给它的构造函数。但请记住,这些参数在后续阶段将改变(变化),并且必须按照已有状态使用。

class MyStatelessWidget extends StatelessWidget {

	MyStatelessWidget({
		Key key,
		this.parameter,
	}): super(key:key);

	final parameter;

	@override
	Widget build(BuildContext context){
		return new ...
	}
}
复制代码

即使有另一个方法可以被重写(createElement),后者也几乎不会被重写。唯一需要被重写的是 build 方法。

这种 Stateless Widget 的生命周期是相当简单的:

  • 初始化
  • 通过 build() 渲染
Stateful Widget

其他一些 Widget 将处理一些在 Widget 生命周期内会发生变化的内部数据。因此,此类数据会变为动态

该 Widget 所持有的数据集在其生命周期内可能会发生变化,这样的数据被称为 State

这些 Widget 被称为 Stateful Widget

此类 Widget 的示例可能是用户可选择的复选框列表,也可以是根据条件禁用的 Button 按钮。

State 的概念

State 定义了 StatefulWidget 实例的 “行为”。

它包含了用于 交互 / 干预 Widget 信息:

  • 行为
  • 布局

应用于 State 的任何更改都会强制 Widget 进行重建

State 和 Context 的关系

对于 Stateful WidgetStateContext 相关联。并且此关联是永久性的,State 对象将永远不会改变其 context

即使可以在树结构周围移动 Widget Context,State 仍将与该 context 相关联。

StateContext 关联时,State 被视为已挂载

重点

State 对象context 相关联,就意味着该 State 对象

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值