news 2026/9/21 15:09:24

Flet 0.83.0 版本解读:更快的控件 diff、更精简的打包与通往 1.0 的工程化之路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flet 0.83.0 版本解读:更快的控件 diff、更精简的打包与通往 1.0 的工程化之路

Flet 0.83.0 版本解读:更快的控件 diff、更精简的打包与通往 1.0 的工程化之路

【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet

Flet 0.83.0 是一次面向"地基"的发布:它重写了命令式与声明式两种编程风格下的控件 diff 机制,将桌面客户端二进制与构建模板从 PyPI 迁移到 GitHub Releases,并引入基于Annotated类型的声明式字段校验。本文将以该版本发布公告为骨架,结合当前仓库中的 Python SDK 源码,逐项拆解这些改进的实现原理、升级步骤与对日常开发的实际影响,帮助你理解 0.83.0 的底层变化并在自己的应用中平滑升级。

如何升级到 0.83.0

0.83.0 的升级方式与以往保持一致,根据你使用的依赖管理工具选择对应命令:

使用 pip 直接升级(含全部平台扩展):

pip install 'flet[all]' --upgrade

使用 uv 并维护pyproject.toml,希望整体同步所有依赖:

uv sync --upgrade

只想升级 Flet 相关包(框架本体、CLI、桌面运行时、Web 运行时),保持其他依赖不动:

uv sync --upgrade-package flet \ --upgrade-package flet-cli \ --upgrade-package flet-desktop \ --upgrade-package flet-web

注意:0.83.0 起flet-desktop包的结构发生了根本变化(见下文"打包重构"章节),升级后首次运行桌面应用时会有一个一次性初始化下载过程,这属于正常行为。

更快的控件 diff:从"遍历全屋"到"只查拨动的开关"

Flet 应用本质上是一个 Python 到 Flutter 的桥:每次调用page.update()或重建声明式组件时,框架都要计算一个 diff——即"哪些属性发生了变化、需要同步给 Flutter 客户端"的集合。0.83.0 之前,这个过程是无差别全量比较;0.83.0 则针对命令式和声明式两种编程风格分别做了机制性重构。

命令式应用:Prop描述符与稀疏脏标记

改动前:每次page.update()都会遍历控件上的所有属性并与上一份快照逐一比较,哪怕你只改了一个属性。一个拥有 20 个属性的控件,即使只改了 1 个,Flet 也要把 20 个全部比较一遍。

改动后:新的Prop描述符负责追踪"自上次 diff 以来,哪些属性被真正写入过"。当你执行button.text = "Click me"时,只有text被标记为 dirty;下一次page.update()只把 dirty 属性发给 Flutter,其余属性全部跳过。打个比方:以前是每层楼每个房间都巡检一遍,现在只检查你真正拨动过的那几个开关。

从源码看,这一机制的核心实现在 value_types.py:Prop是一个实现了__get__/__set__的数据描述符,它把"非默认值"稀疏地存入控件的_values字典:

  • 赋值时如果新值等于声明默认值,直接丢弃(恢复稀疏性);
  • 如果新值与旧值相等,直接短路返回(无变化则不触发任何同步);
  • 否则写入_values并标记obj._dirty[self.name],随后触发_notify通知。

_values_dirty这两个内部字典定义在 base_control.py,并在__post_init__末尾执行self._dirty.clear()(base_control.py),保证"构造过程不算变更"——只有构造之后的显式赋值才会进入 diff 视野。这意味着冻结(frozen)diff 快路径只需取两个对象_values字典的键并集,而无需扫描所有已声明字段。

声明式应用:@value装饰器与按内容比较

改动前:声明式组件重建时,Flet 会逐一比较新旧控件树的每个字段——包括AlignmentBorderRadiusBoxDecoration这类嵌套值对象。由于每次 build 都会重新创建这些对象,即使内容一模一样,它们按对象身份比较时也永远"看起来是新的",导致整个子树无法被跳过。

改动后:约 150 种数据类型改用新的@value装饰器,使其按内容而非身份进行相等比较;再配合"先检查结构性变化、再只比较真正有差异的字段"的两遍 diff,未变化的子树可以被整体跳过。

@value装饰器的实现在 value_types.py:它本质上是一个@dataclass_transform装饰器,内部先应用@dataclass,再通过_install_props()把公开字段替换为Prop描述符、记录非 Prop 的结构性字段,并在__init__中注入_values/_dirty后于构造末尾清空 dirty 标记。同时它把类注册为Value的虚拟子类(value_types.py),使 diff 机制可以通过isinstance(obj, Value)快速识别这类值类型。该模块之所以独立成文件,正是为了避免与base_control形成循环导入(DurationAlignment等值类型被base_control间接引用)。

基准数据

官方在 Python 3.14.2、Apple Silicon 环境下测得(详见发布公告):

场景提升幅度
冻结控件(20 字段、改动 2 个,100–300 个控件)3.2–3.4× 更快
混合 keyed/unkeyed 列表1.9–2.0× 更快
非冻结重建列表2.9–4.5× 更快
Sunflower 声明式示例(500 粒种子)6.7× 更快

其中作为基准的 Sunflower 示例在仓库中位于 sunflower/main.py,是一个"用滑块实时重算声明式布局"的动画应用:Seed数据类与AppModel通过ft.Observable驱动状态,SeedView组件被ft.memo包裹,构建了由数百个带 key 的Container组成的Stack(当前仓库中该示例的种子总数上限为 250,公告基准中记载为 500,量级一致)。ft.memo正是依赖"值类型按内容比较"来避免无谓重建的关键场景,感兴趣的读者可以对照 memo.py 阅读。

更智能的.update():自动更新不再重复触发

旧版本中,Flet 会在每个事件处理函数执行结束时自动调用一次page.update()。如果你的处理函数里已经显式调用过.update()(例如先弹出一个 spinner 再开始耗时工作),框架就会在末尾再触发一次冗余 update,可能造成视觉闪烁或无效工作。

0.83.0 起,框架会追踪处理函数执行期间是否已经调用过.update():调用过则末尾的自动更新被跳过。这一改动还带来一个重要的兼容性收益——从 Flet 0.28.3(没有自动更新机制的版本)"原样迁移"过来的应用,无需任何改动即可获得与旧版本一致的行为。

对于追求精细控制的开发者,这意味着你既可以利用"事件末尾自动刷新"的便利,也可以在关键路径上显式update()并放心它不会被重复执行。

声明式字段校验:Annotated+V规则集

0.83.0 为控件字段引入了声明式校验能力:字段可以内联声明校验规则,替代在__init__before_update()里手写检查代码。规则使用 Python 标准的Annotated类型元数据表达:

from typing import Annotated from flet.core.validation import V entries: Annotated[list, V.or_(V.empty, V.min_length(3))]

这条声明表达的含义是:entries字段要么为空、要么长度至少为 3,二者满足其一即通过校验。约束与字段定义写在一起,让人一眼就能看出该字段的不变量。

这一特性在当前仓库的 SDK 中已经有实际应用。例如 control.py 中所有控件基类共有的expand字段:

expand: Annotated[ Optional[Union[bool, int]], V.instance_of((bool, int)), ] = None

当传入非bool/int类型时,赋值阶段即抛出ValueError(其 docstring 中的Raises: ValueError正是由该规则驱动的)。同样地,opacity字段使用了V.between(0.0, 1.0)约束取值范围(control.py)。

V规则构建器定义在 validation.py,它提供一系列静态方法,返回可附加到Annotated[...]字段或类级__validation_rules__FieldRule/ClassRule实例。以组合规则V.or_为例,其实现会校验传入参数均为FieldRule、至少一个规则(否则抛出ValidationDeclarationError),并在运行时按声明顺序求值、任一规则通过即成功(validation.py)。大多数字段级规则在字段注解为可选类型时会自动放行None,避免与"未设置"状态冲突。

配合规则集,弃用字段还能通过V.deprecated规则(validation.py)在赋值时发出一次性弃用警告,并携带versiondelete_versiondocs_reason等元数据——文档工具会自动为弃用字段生成提示性告示,省去了手工维护文档的负担。

打包重构(一):客户端二进制从 PyPI 迁移到 GitHub Releases

此前,Flet 的桌面客户端(面向 Windows、macOS、Linux 的 Flutter 运行时)被打进 PyPI wheel 里分发,导致 wheel 体积巨大、持续消耗 PyPI 存储空间。从 0.83.0 起,这一做法被彻底改变:

  • 桌面客户端改为首次运行时从 GitHub Releases 下载,并缓存在本机~/.flet/client/
  • flet-desktop包变成一个单一、体积小巧、与平台无关的 wheel。

这对开发者意味着:

  • 安装更快pip install flet下载的是小体积 wheel,不再夹带平台特定二进制;
  • 包更统一:独立的flet-desktop-light包被移除,通过FLET_DESKTOP_FLAVOR环境变量或pyproject.toml中的[tool.flet]配置在 "light"/"full" 两种风味间选择;Linux 上未指定时默认使用 "light" 风味;
  • 支持离线环境:通过FLET_CLIENT_URL环境变量指向本地镜像,即可在无法访问 GitHub 的内网环境中完成客户端获取。

源码印证了完整的解析与下载链路。在 flet-desktop/src/flet_desktop/init.py 中,__get_desktop_flavor()按以下优先级解析风味:FLET_DESKTOP_FLAVOR环境变量 → 当前目录pyproject.toml[tool.flet].desktop_flavor→ 默认值(Linux 为"light",其他平台为"full")。下载逻辑在__download_flet_client()(同文件 L309-L331):默认 URL 由包内嵌入的版本号构造(https://github.com/flet-dev/flet/releases/download/v{ver}/...),并可用FLET_CLIENT_URL整体覆盖;ensure_client_cached()则负责管理~/.flet/client/缓存目录,同时兼容 PyInstaller 打包场景下"包内附带归档"的降级路径。此外,Linux 客户端选择还会结合 glibc 版本与发行版 ID 挑选匹配的构建目标(同文件 L99-L124)。

打包重构(二):构建模板迁移到 GitHub Releases

与此配套,原先独立的flet-build-templateflet-app-templates仓库被合并进 Flet 主仓库,构建模板改为以 zip 归档形式挂载在每次 GitHub Release 上。

当你执行flet buildflet create时,CLI 会下载与你当前安装的 Flet 版本精确匹配的模板 zip——版本被锁定,即使是预发布版本也一样。这彻底消除了框架与构建模板版本不匹配的老问题。

对于稳定版发布,fletFlutter 包照常发布到 pub.dev;而对于预发布版本,构建模板会通过 Git 依赖直接引用精确的 commit SHA——从而保证flet build编译所用的 Flutter 代码与你的 Python 包版本严格一一对应。

更好的发布可追溯性

0.83.0 强化了版本追溯能力:

  • GitHub 预发布(Pre-releases):每个开发构建都会生成一个 GitHub Release(如v0.83.0.dev6045)。你可以直接浏览预发布列表,精确了解每个开发版本修复了哪些问题、引入了哪些特性,不再需要猜测某个 bug 修复是否已进入最新 dev 版本。
  • Issue/PR 里程碑(Milestones):issue 与 PR 现在会被指派到里程碑。想确认某个 issue 何时被修复?查看其里程碑即可得知对应的发布版本号。

通往 1.0:工程化与质量基础设施

0.83.0 的另一面是"可持续性"投入,这直接服务于 Flet 1.0 的目标:

  • 端到端自动化:CI 流水线覆盖构建、测试、打包、发布全流程。每次推送到main都会触发全平台二进制构建、测试套件运行、所有目标的flet build验证,以及向 GitHub 和 pub.dev 发布 dev 版本,全程无人工步骤。
  • 全面集成测试:目前已在 macOS 上运行 200+ 项集成测试,分布在 12 个并行测试套件中,覆盖核心控件、Material 与 Cupertino 组件、服务、主题、扩展和示例应用;完整跑一遍约需 85 分钟,能够在缺陷到达用户之前捕获回归。其他平台的集成测试套件正在推进中(仓库中示例的截图金样目录如 packages/flet/integration_tests/examples/apps/golden/macos 即为该体系的产物)。
  • 文档体系升级:Flet 文档将回归 Docusaurus 构建,带来更好的阅读体验、更优的搜索和更顺畅的贡献流程。

其他变更与 Bug 修复

0.83.0 还包含一批值得关注的功能与修复:

  • 可定制滚动条(#6282):滚动条的样式与行为可配置。
  • 可滚动的ExpansionPanelList(#6294):面板列表内容超出视口时可滚动。
  • SharedPreferences支持更多类型(#6267):现在支持intfloatboollist[str]。源码中其类型别名定义为SharedPreferencesValueType: TypeAlias = Union[str, int, float, bool, list[str]](shared_preferences.py),set()方法会校验值类型并对不支持的类型抛出ValueError(shared_preferences.py)。
  • 对齐 Python 与 Dart 默认值(#6330):跨所有包统一两侧的默认参数。
  • 修复ReorderableListView事件反序列化(#6315):on_reorder_start/on_reorder_end的事件载荷得到修正。从源码看,这两个事件的 payload 是OnReorderEvent(reorderable_list_view.py),其中old_index仅在on_reorder_start/on_reorder时非空,new_index仅在on_reorder/on_reorder_end时非空,本次修复保证了两者能被正确解析。
  • 跳过带pyproject.toml应用的 micropip 加载(#6300):Web 端初始化路径优化。

总结

Flet 0.83.0 是典型的"地基型"版本:Prop描述符 +@value装饰器让命令式与声明式应用的 diff 效率获得数倍提升,Annotated+V把校验从手写逻辑变成声明式约束,客户端二进制与构建模板迁移到 GitHub Releases 让安装更轻、版本更可控,而预发布与里程碑机制让每个构建都可追溯。这些底层改进具有复利效应——后续每个版本都会建立在更快、更可靠的基础上。

对于应用开发者,本版本的实践要点可以概括为三条:升级时记得用--upgrade-package只升 Flet 相关包;升级后首次运行桌面应用会有一次性客户端下载;如果处于内网环境,提前用FLET_CLIENT_URLFLET_DESKTOP_FLAVOR(或[tool.flet]配置)完成部署规划。

【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 15:08:29

Java日期处理:获取N天前日期的最佳实践

1. 需求背景与场景解析在日常开发中,处理日期时间是最基础却最容易出错的环节之一。上周我就遇到一个典型场景:业务系统需要自动生成以"yyyyMMdd"格式命名的报表文件,但必须基于两周前的日期作为基准。类似这种"获取N天前日期…

作者头像 李华
网站建设 2026/9/21 15:06:43

半桥LLC软启动5大常见错误与解决方案

1. 半桥LLC软启动到底难在哪半桥LLC谐振变换器在中小功率电源里几乎是绕不开的拓扑,效率高、EMI友好、原副边隔离容易做,但凡做过300W以上适配器或者LED驱动的朋友,大概率都碰过它。可真正让工程师头疼的往往不是稳态效率,而是软启…

作者头像 李华
网站建设 2026/9/21 14:57:46

海康大华RTSP取流地址与播放方案实战指南:从URL格式到踩坑排查

前阵子给一条产线做视觉检测,现场混了十六路海康IPC、两台大华NVR,还有几个第三方球机要统一接入算法平台。头一天我以为半天能搞定,结果从下午两点死磕到晚上十一点,一半时间都浪费在“同一个RTSP标准协议,为什么地址…

作者头像 李华
网站建设 2026/9/21 14:44:12

Python大数据微博舆情分析系统设计与实现

1. 项目背景与核心价值微博作为国内最大的社交媒体平台之一,每天产生海量的用户生成内容。这些数据蕴含着丰富的舆情信息,对企业和机构来说具有重要的商业和社会价值。传统的舆情监测方式往往依赖人工抽样分析,效率低下且难以全面把握舆情动态…

作者头像 李华