跳到主要内容

11 篇博文 含有标签「发布」

查看所有标签

· 阅读需 7 分钟
Feodor Fitsner

Flet 0.27.0 现已发布,带来了令人兴奋的新功能和改进!

  • iOS 打包和签名更新 – 确保符合 App Store Connect 验证要求。
  • 减少启动延迟 – 桌面应用程序的初始启动速度更快。
  • 更快的增量重建 – 通过更快的迭代时间提高开发效率。
  • 增强的下拉菜单控件 – 改进的功能和用户体验。
  • 错误修复和稳定性改进 – 各种修复以提高整体性能和可靠性。

如何升级

运行以下命令升级 Flet:

pip install 'flet[all]' --upgrade
备注

[all]是一个“额外”说明符,它告诉 pip 安装或升级所有flet包:fletflet-cliflet-desktopflet-web

在你的pyproject.toml中将flet包版本提升到0.27.0(或者完全删除它以使用最新版本)。

改进的 iOS 打包

  • 第三方 Flet 应用程序依赖项(也称为“站点包”,如numpypandasflet等)现在捆绑在一个框架内,确保 Xcode 正确签署所有文件并通过 App Store Connect 验证。
  • 新的flet build选项用于正确的 iOS 包签名。
  • 用于打包和部署 iOS 应用程序的全面分步文档。了解更多!

提高桌面应用程序的启动性能

目前,在为 macOS、Windows 和 Linux 打包时,第三方 Flet 应用程序依赖项(例如numpypandasflet等),也称为站点包,被捆绑在 app.zip 工件内。这可能会导致启动延迟,有时会很明显,因为应用程序在启动前需要将工件提取到用户的文件系统中。

在 Flet 0.27.0 中,站点包现在以未打包状态直接复制到应用程序包中,而不是压缩到 app.zip 中。这一变化显著减少了首次启动时间。

更快的增量重建

如果构建配置的某些部分保持不变,flet build命令会尝试跳过或优化特定的构建管道步骤(例如重新安装 Flet 应用程序依赖项),减少连续构建的总体完成时间。

更快的构建意味着更快乐的开发者! 😄

Pyodide 0.27.2

Pyodide 0.27.2 基于 Python 3.12,对外函数接口(FFI)有一些重大的性能改进。

Flet 现在在所有打包平台上支持 Python 3.12。

下一站是 Python 3.13!

增强的Dropdown控件。

从 0.27.0 版本开始,Flet 对Dropdown控件使用DropdownMenu flutter 小部件,这是之前使用的 DropdownButton 的 Material 3 版本。除了增强的外观和感觉之外,它还允许根据文本输入过滤列表或在菜单列表中搜索一个项目。

上一个 Dropdown 实现的一些属性在新版本中不可用,并被“存根化”——它们不会破坏你的程序,但也不会做任何事情。请在此处查看已弃用属性的列表[/docs/controls/dropdown/#deprecated-dropdown-properties-and-events]。

上一个版本的 Dropdown 控件可作为DropdownM2控件使用,并将在 Flet 0.30.0 中删除。

💥 重大变化

flet build命令

  • --team选项重命名为--ios-team-id
  • --include-packages已被删除。只需将扩展包添加到你的pyproject.toml文件的dependencies部分:https://flet.dev/docs/extend/built-in-extensions
  • 删除了--cleanup-on-compile,并添加了两个新选项来分别清理应用程序和第三方站点包:--cleanup-app--cleanup-packages。另外两个选项:--cleanup-app-files--cleanup-package-files--cleanup-*一起使用,并允许指定要从应用程序和站点包中排除的 glob 列表。
  • tool.flet.build_arch重命名为tool.flet.target_arch

删除 v0.24.0 中的弃用项

在 Flet 0.24.0 中弃用的以下项目已被删除:https://flet.dev/blog/flet-v-0-24-release-announcement#deprecations

CupertinoCheckbox.inactive_color属性

CupertinoCheckboxinactive_color属性已被删除,取而代之的是fill_color

其他变化

完整的更改列表可以在CHANGELOG中找到。

新功能

  • feat: ReorderableListView控件(#4865)
  • feat: 实现Container.dark_theme属性(#4857)
  • 升级到 Pyodide 0.27 以支持httpx(#4840)
  • 删除CupertinoCheckbox.inactive_color,取而代之的是fill_color(#4837)
  • feat: flet build:使用配置文件签署 iOS 应用程序归档(.ipa),弃用--team选项(#4869)
  • feat: flet doctor命令行命令(#4803)
  • feat: 实现按钮主题(对于ElevatedButtonOutlinedButtonTextButtonFilledButtonIconButton)(#4872)
  • feat: ControlEvent.data应该是Optional[str]类型,并默认为None(#4786)
  • feat: flet build:添加--source-packages以允许从源发行版安装某些 Python 包(#4762)

错误修复

  • 修复:禁用 stdout 日志的 rich 的 Markup(#4795)
  • 修复:设置SearchBar.bar_border_side在视觉上未被遵守(#4767)
  • 修复:下拉菜单:长选项导致向下箭头溢出(#4838)
  • 修复:CupertinoSlider 初始化不允许值小于零/大于 1(#4853)
  • 修复:相同的代码在 Flet APP/Web/PC 本地显示不同的外观。(#4855)
  • 修复:变换比例会呈现灰色屏幕(#4759)
  • 修复:在 manifest.json 中使用带重音的字符时出现 UnicodeDecodeError(#4713)
  • 修复:实现SearchBar.blur()以通过编程方式取消聚焦栏(#4827)
  • 修复:禁用 flet-cli stdout 日志的 markup(#4796)

结论

升级到 Flet 0.27.0,测试你的应用程序,并让我们知道你对我们添加的新功能的感受。

如果你有任何问题,请加入Flet Discord 服务器或在Flet GitHub 讨论上创建一个新线程。

快乐地使用 Flet!👾

· 阅读需 6 分钟
Feodor Fitsner

Flet 0.26.0 版本已发布,在可扩展性方法方面有重大更新!

总之,Flet 扩展现在是一个单一的 Python 包,它捆绑了 Python 和 Flutter 代码。这个包可以是你的 Flet 项目的一部分,也可以托管在公共 Git 存储库或 PyPI 中。

内置的 Flet 扩展,如“音频”、“视频”和“地图”,已被移动到它们自己的存储库中。欢迎你分叉这些扩展来创建自己的扩展或为 Flet 做出贡献!这些扩展已发布到 PyPI,使它们很容易包含在你的 Flet 应用程序中。要使用它们,只需将所需的扩展添加到你的“pyproject.toml”文件的“dependencies”部分。

如何升级

运行以下命令来升级 Flet:

pip install 'flet[all]' --upgrade
备注

“[all]”是一个“额外”说明符,它告诉 pip 安装或升级所有“flet”包:“flet”、“flet-cli”、“flet-desktop”和“flet-web”。

在你的“pyproject.toml”中将“flet”包版本提升到“0.26.0”(或者完全删除它以使用最新版本)。

可扩展性变化

内置扩展

基于曾经是 Flet 存储库一部分的第三方 Flutter 包的 Flet 控件现在已被移动到单独的存储库并发布在 PyPI 上:

要在你的项目中使用内置的 Flet 扩展,将其添加到你的“pyproject.toml”文件的“dependencies”部分,例如:

dependencies = [
"flet-audio",
"flet>=0.26.0",
]

用户扩展

Flet 现在使你可以轻松地基于 Flutter 小部件或 Flutter 第三方包创建和构建具有自定义控件的项目:

  1. 创建新的虚拟环境并在那里安装 Flet
  2. 从模板创建新的 Flet 扩展项目:
flet create --template extension --project-name my-control

将创建一个带有新的 MyControl 控件的项目。该控件只是一个具有单个“text”属性的 Flutter Text 小部件。 3. 构建你的应用程序。

从扩展模板创建的 Flet 项目在“examples/my_control_example”文件夹中有示例应用程序。

当在你的应用程序的“pyproject.toml”所在的文件夹中时,运行“flet build”命令,例如,对于 macOS:

flet build macos -v

运行应用程序并查看新的自定义 Flet 控件:

open build/macos/my-control-example.app

在这里阅读更多关于如何自定义你的扩展[/docs/extend/user-extensions]。

开发环境配置

为了增强使用“flet build”命令的开发人员体验,Flet 0.26.0 确保安装了正确版本的 Flutter SDK、Java(JDK)和 Android SDK。如果其中任何一个缺失或过时,它会自动为你安装。

如果你正在为 Windows 构建 Flet 应用程序,你仍然需要自己安装 Visual Studio 2022,或者如果你正在为 iOS 或 macOS 构建,则需要安装 Xcode。

在接下来的版本中,我们将引入 Android 和 iOS 模拟器的自动配置和启动。

Flutter 3.27

Flet 已迁移到 Flutter SDK 3.27。有关新的和更新的控件属性,请参阅此拉取请求

Python 3.9

Flet 0.26.0 需要 Python 3.9 或更高版本。Python 3.8 已达到EOL

其他变化

  • 可选的按需创建“ListView.controls”(#3931)
  • 重置“InteractiveViewer”变换(#4391)
  • 从主窗口传递鼠标事件到其他应用程序(#1438)
  • 实现“Window.ignore_mouse_events”(#4465)
  • 添加 Google/Android TV 平台支持(#4581)
  • 从预定义的类型“*Value”中删除“Optional[]”(#4702)
  • 限制“InteractiveViewer”更新事件(#4704)
  • 删除与 v0.26.0 相关的弃用(#4456)

错误修复

  • 修复:更新 project_dependencies.py(#4459)
  • 修复:“SafeArea”对象没有属性“_SafeArea__minimum”(#4500)
  • 修复:在“update()”上“Segment”和“BarChartRod”中的工具提示损坏(#4525)
  • 修复:将“CheckBox.border_side.stroke_align”设置为枚举失败(#4526)
  • 修复:“ControlState”应根据用户定义的顺序解析(#4556)
  • 修复:损坏的“Dismissible.dismiss_direction”(#4557)
  • 修复:修复 Rive 不更新(#4582)
  • 修复:“DatePicker”与第一个和最后一个日期的回归问题(#4661)
  • “flet build”命令:复制“flutter-packages”,支持特定于平台的依赖项(#4667)
  • 修复:“CupertinoBottomSheet”将红色和黄色下划线应用于“Text”内容(#4673)
  • 修复:设置“ButtonTheme”显示灰色屏幕(#4731)
  • 修复:“Textfield”输入边框颜色考虑用户指定的“border_color”属性(#4735)
  • 修复:使“Tooltip.message”成为必需参数(#4736)

结论

升级到 Flet 0.26.0,测试你的应用程序,并让我们知道你对我们添加的新功能的看法。

如果你有任何问题,请加入Flet Discord 服务器或在Flet GitHub 讨论上创建一个新线程。

快乐地使用 Flet!👾

· 阅读需 10 分钟
Feodor Fitsner

问题

当您将 Flet 程序打包成在移动设备(或桌面设备)上运行的 Python 程序时,生成的包(.apk、.ipa、.exe、.app)包含您的 Python 程序、Python 解释器和 Python 标准库

如果您的程序只使用 Python 标准库,那么打包过程相对简单——Flet 会将您的代码压缩并将 Flutter 应用程序与为目标平台(Android 或 iOS)编译的 Python 解释器和标准库组合在一起。

然而,当您的 Flet 程序使用第三方包时,可能会出现问题,而这些包有数千个发布在 PyPI 或 Conda 上。

第三方包有两种类型:

纯 Python 包

“纯 Python”包是仅包含 Python 代码的包,不包括用 C、C++、Rust 或其他语言编写的扩展。您只需要一个 Python 解释器和 Python 标准库即可运行纯 Python 包,而无需关心您的操作系统或平台。

此类包的示例:httpxclickrichrequests

要验证包是否纯粹,请在 PyPI 上找到该包并导航到其“下载文件”页面。如果在“已构建分发”部分下只有一个以 -py3-none-any.whl 结尾的 wheel,那么很可能它是一个纯 Python 包,可以在任何带有 Python 的设备上“按原样”运行。

我们说*“可能”*是因为该纯包可能依赖于非纯包,例如 pydantic 是一个纯包,但它需要使用 Rust 编写的 pydantic-core 非纯包才能正常工作。

非纯 Python 包

“非纯 Python”包是部分或全部用 C、C++、Rust 或其他语言编写并必须为其运行的平台编译为机器码的包。

此类包的示例:cryptographyopencv-pythonnumpymsgpack

在非纯包的“下载文件”页面上,您会发现为各种平台预构建的轮子:macOS、Windows、Linux。

当您运行 pip install <package> 时,pip 会尝试根据轮子后缀查找特定平台和 Python 版本的轮子。

这是包开发者提供的礼貌行为,为多个平台提供预编译的轮子。某些平台可能缺少轮子,或者没有轮子——只有“源分发”中的 .tar.gz 包含包源代码。

从源代码构建包很难

要安装仅具有源代码分发的包,pip 会尝试使用安装的编译器、链接器、库和 SDK 在您的机器上构建非 Python 代码。然而,这个过程可能既漫长又容易出错。编译后的代码库可能很大,并且您的机器可能缺少所需的库或工具链。

还没有适用于 iOS 和 Android 的轮子

PyPI 上还没有适用于 iOS 和 Android 的预构建轮子,并且 PyPI 的验证过程不允许包开发者上传这些轮子,因为 iOS 和 Android 都不是 Python 的正式支持平台。

有一个过程(PEP 730PEP 738)将为 Python 3.13 添加对 iOS 和 Android 的正式支持,因此,希望开发者体验将有所改善。

包依赖关系

纯 Python 包可以导入或依赖非纯包,在将您的 Flet 应用程序打包以在移动设备上运行时,您应该牢记这一点。

例如,supabase 包用于访问 Supabase API,是一个依赖于 pydantic 包的纯包,而 pydantic 包本身依赖于用 Rust 编写的 pydantic-core 非纯包。因此,要运行使用 Supabase API 的 Flet 应用程序,打包过程应该能够找到适合目标平台的预构建轮子。如果 PyPI 没有该轮子,那么要么是 Flet 开发人员在他们的服务器上构建该轮子并托管它,要么是您在自己的机器上构建该轮子。

要查看包的依赖关系图,您可以使用 pipgrip

使用 --tree 选项运行它以获得依赖关系树视图:

$ pipgrip --tree fastapi

fastapi (0.110.3)
├── pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4 (2.7.1)
│ ├── annotated-types>=0.4.0 (0.6.0)
│ ├── pydantic-core==2.18.2 (2.18.2)
│ │ └── typing-extensions!=4.7.0,>=4.6.0 (4.11.0)
│ └── typing-extensions>=4.6.1 (4.11.0)
├── starlette<0.38.0,>=0.37.2 (0.37.2)
│ └── anyio<5,>=3.4.0 (4.3.0)
│ ├── idna>=2.8 (3.7)
│ └── sniffio>=1.1 (1.3.1)
└── typing-extensions>=4.8.0 (4.11.0)

当前方法

我们在4 个月前发布了打包的第一个版本,自那时以来,我们意识到初始方法存在多个缺陷,需要改进。

当您使用当前版本的 Flet 运行 flet build apk 时,它会下载为 Android(或如果使用 flet build ipa 运行时为 iOS)预构建的 Python 运行时和标准库。

对于非纯包,例如 numpy,Flet 要求您使用 Kivy 的“Python for Android”(p4a)工具自行构建这些包,然后提供一个路径到预构建包可以找到的“p4a”分发包。

这是问题 #1 - 您被迫与在您的机器上安装“p4a”工具并编译 Python 模块的复杂过程作斗争。

问题 #2 - 来自 p4a 的 dist 目录中的所有包将被包含在最终的应用程序包中 - 它可能包含无关的包和其他垃圾。

问题 #3 - 非纯包必须在运行 flet build 命令之前构建。您必须分析应用程序的所有依赖项,并分离出必须使用 p4a 构建的内容。

问题 #4 - p4a 的“配方”可能非常旧或缺失。您希望旧版本的包适用于您的应用程序,尝试编写“配方”并希望它能工作,或者在 Kivy 存储库中提交新配方的请求。

当您完成使用 p4a 构建非纯包时,Flet 要求您在 requirements.txt 中仅指定纯包,这在纯包直接或间接依赖于非纯包时不起作用(请参见上述示例) - 这是问题 #5。有一个最近的例子说明了这个问题:flet buildrequirements.txt 中用 flet-embed 替换 flet,但它无法知道是否有第三方包依赖于 flet,因此会安装 flet-embed 和不适用于移动设备的 flet。这不是解决方案,而是一个黑客!

打包 2.0

在 Flet 打包实现的下一次迭代中,我们将放弃 Kivy 并用 Mobile Forge 取而代之。Mobile Forge 是由 Beeware 团队基于他们在 Briefcase 和 Chaquopy 上的经验创建的。Mobile Forge 是一个用于二进制 Python 包的打包工具的清洁实现,依赖于 crossenv

Mobile Forge 和 crossenv 的主要承诺是,大多数现有的非纯 Python 包将能够通过简单地添加一个 meta.yaml 文件的配方来为 iOS 和/或 Android 编译,而无需任何黑客或补丁。

我们将使用 Mobile Forge 为 iOS 和 Android 预构建最流行的非纯 Python 包,并在我们自己的公共存储库中托管它们。您将能够使用该工具来构建和贡献其他不在我们存储库中的包。

我们在 Flet 讨论中创建了一个新的“包”类别,您可以在其中发布、投票和讨论适用于 Flet 的非纯(本机)Python 包的请求(在发布之前请查看规则)。Flet 的目标是提供最全面的预构建 Python 包目录,并使添加新包的过程尽可能友好和透明。

新版本的 flet build 将使用自定义的虚拟 pip 索引。此索引将分析依赖项,检测非纯包,并提供 pip 移动包。对于所有其他包,它将回退到 PyPI。

希望新的打包版本将在几周内可用。在我们工作期间,我们鼓励您访问并查看您需要的包是否在那里。提交请求或为现有包投票将帮助我们优先处理包的“配方”。

谢谢!

· 阅读需 6 分钟
Henri Ndonko

在发布 Flet 0.21.0 一个多月后,我们很高兴地宣布发布 Flet 0.22.0。

此版本带来了许多增强、错误修复和弃用功能:

增强功能

这是本次发布的主要关注点之一。我们进行了两种类型的增强:

控件增强

我们遍历了现有控件的长列表,并在可能的情况下公开了更多属性 - PR #2882。这将为您提供更多对 Flet 控件的控制,以便在您的优秀应用程序中使用。

以下是完整列表:

  • AppBar: elevation_on_scroll, exclude_header_semantics, force_material_transparency, is_secondary, shadow_color, surface_tint_color, clip_behavior, title_spacing, toolbar_opacity, title_text_style, toolbar_text_style, shape
  • AlertDialog: action_button_padding, clip_behavior, icon_padding, shadow_color, surface_tint_color
  • Banner: content_text_style, margin, elevation, divider_color, shadow_color, surface_tint_color, on_visible
  • CupertinoListTile: leading_size, leading_to_title
  • CupertinoSegmentedButton: click_color
  • CupertinoSwitch:on_label_color, off_label_color
  • CupertinoTimerPicker: item_extent
  • Chip: surface_tint_color, color, click_elevation, clip_behavior, visual_density, border_side
  • Divider: leading_indent, trailing_indent
  • ExpansionTile: dense, enable_feedback, visual_density
  • Card: clip_behavior, is_semantic_container, show_border_on_foreground, variant
  • Checkbox: border_side, semantics_label, shape, splash_radius, is_error, visual_density, mouse_cursor
  • CircleAvatar: on_image_error
  • DataTable: clip_behavior
  • DatePicker: on_entry_mode_change
  • Draggable: on_drag_complete, on_drag_start
  • DragTarget: on_move
  • Dropdown: fill_color, hint_content, icon_content, elevation, item_height, max_menu_height, icon_size, enable_feedback, padding, icon_enabled_color, icon_disabled_color, on_click
  • ElevatedButton: clip_behavior
  • FloatingActionButton: clip_behavior, enable_feedback, focus_color, foreground_color, disabled_elevation, elevation, focus_elevation, highlight_elevation, hover_elevation, mouse_cursor
  • GridView: cache_extent, clip_behavior, semantic_child_count
  • IconButton: alignment, disabled_color, focus_color, enable_feedback, hover_color, padding, splash_color, splash_radius, focus_color, mouse_cursor, visual_density
  • Image: exclude_from_semantics, filter_quality
  • ListTile: enable_feedback, horizontal_spacing, min_leading_width, min_vertical_padding, selected_color, selected_tile_color, style, title_alignment, icon_color, text_color, shape, visual_density, mouse_cursor, title_text_style, subtitle_text_style, leading_and_trailing_text_style
  • ListView: cache_extent, clip_behavior, semantic_child_count
  • NavigationBar: animation_duration, overlay_color
  • NavigationDrawerDestination: bgcolor
  • NavigationDestination: bgcolor
  • NavigationRail: selected_label_text_style, unselected_label_text_style
  • NavigationRailDestination: indicator_color, indicator_shape
  • Option: alignment, on_click
  • OutlinedButton: clip_behavior
  • Page: locale_configuration
  • PopupMenuItem: height, padding, mouse_cursor
  • PopupMenuButton: bgcolor, clip_behavior, elevation, enable_feedback, icon_color, shadow_color, surface_tint_color, icon_size, padding, splash_radius, shape, on_open, on_cancel
  • ProgressBar: border_radius, semantics_label, semantics_value
  • ProgressRing: semantics_label, semantics_value, stroke_cap, stroke_align
  • Radio: focus_color, hover_color, overlay_color, splash_radius, toggleable, visual_density, mouse_cursor
  • SearchBar: keyboard_type, view_surface_tint_color, autofocus
  • SelectionArea: on_change
  • Slider: interaction, overlay_color, mouse_cursor, secondary_track_value, secondary_active_color
  • Stack: alignment, fit
  • SnackBar: clip_behavior, shape, on_visible, action_overflow_threshold
  • Switch: hover_color, splash_radius, overlay_color, track_outline_color, mouse_cursor
  • Tabs: divider_height, enable_feedback, indicator_thickness, is_secondary, mouse_cursor, clip_behavior
  • TextField: fill_color, hover_color
  • TimePicker: orientation, on_entry_mode_change
  • Tooltip: enable_tap_to_dismiss, exclude_from_semantics
  • VerticalDivider: leading_indent, trailing_indent

如果您觉得有些功能缺失且需要添加,请随时告诉我们。

查看我写的关于 Page.locale_configuration 的文章这里

主题增强

用于应用程序主题设置的 Theme 类在浅色和深色模式下得到了进一步增强。 引入了许多新主题 - PR #2955

查看主题指南 这里

Rive 动画

Rive 是一个非常流行的实时交互设计和动画工具。 新引入的 Rive 控件允许您在应用程序中加载和可视化任何 Rive 动画。

动画的来源 (Rive.src) 可以是本地资源文件或 URL - 如常所述,这完全取决于你的需求。

父控件

根据 #952 的请求,已添加访问任何控件父级的功能:Control.parent

阅读更多内容 这里

错误修复

成功修复了以下问题:

  • #2560 - Dropdown.bgcolor 未得到视觉上的尊重
  • #2740 - CircleAvatar 无法与本地资产图像一起使用
  • #2781 - Linux 上引发了 'FletSocketServer' 错误
  • #2826 - PopupMenuItem.data 未得到尊重
  • #2839 - ExpansionTile.initially_expanded 无视觉效果
  • #2867 - PopupMenuButton 始终显示“显示菜单”工具提示
  • 在某些 Python 版本上,您可能会看到 RuntimeError('Event loop is closed'),通常在关闭应用程序窗口时显示。Python-dev 团队最近修复了这一 asyncio 相关的问题,但该修复仅存在于 2024 年发布的版本中。因此,如果您遇到此问题,请下载最新的 Python 版本之一并替换您环境中使用的版本。

特别感谢 Flet 动态社区报告他们遇到的所有问题。我们将继续努力解决剩余的问题。

弃用

如前面在有关 Flet v0.21.0 的 公告 中提到的,所有弃用将在版本 1.0 中完全从 API 中删除 - 因此您有足够的时间来更新您的应用程序。

您无需完全记住哪些内容已弃用,因为我们添加了 DeprecationWarnings,它们将直接显示在您的控制台中(不会破坏您的应用程序)。

文档

Flet 文档已重新组织,以便于导航(特别是对于初学者/新用户)。

升级到 Flet 0.22.0,测试您的应用程序,并告诉我们您对新增功能的看法。 如果您有任何问题,请加入 Flet Discord 服务器 或在 Flet GitHub 讨论 中创建一个新主题。

祝您使用 Flet 愉快!

· 阅读需 9 分钟

Flet 使编写动态的实时 Web 应用程序变得非常有趣!

Flet 0.21.0 进一步改进了 Web 应用程序开发体验以及在 Flet 应用中使用 asyncio API 的体验。

以下是Flet 0.21.0的新功能:

用Uvicorn的FastAPI取代内置Web服务器

从Flet诞生之初开始,用于服务Web应用的内置Web服务器是用Go编写的,名为“Fletd”。当你运行flet run --web命令时,它会在后台启动。Fletd是Flet Python轮子的一部分,增加了几兆字节的大小。此外,Python应用使用WebSockets与Fletd Web服务器通信,有时会增加明显的开销。

Flet 0.10.0中,我们添加了对FastAPI的支持,以使用AsyncIO API构建“严肃的”Web应用。

现在,在Flet 0.21.0中,内置Web服务器已被完全移除,取而代之的是FastAPI和Uvicorn。Fletd不再是Flet分发版的一部分。

使用FastAPI意味着不再有通信开销,因为Web服务器是Flet应用的一部分。此外,你不需要做任何额外的步骤即可使用FastAPI在生产环境中托管你的应用——只需使用相同的ft.app(main)命令运行你的应用。

重大变更

flet_fastapi包已被弃用,其内容已移至flet包中的flet.fastapi模块。如果你在Flet应用中使用了FastAPI,请将:

import flet_fastapi

替换为:

import flet.fastapi as flet_fastapi

使用任何 ASGI Web 服务器进行托管

你可以使用任何兼容 ASGI 的服务器托管你的 Flet Web 应用程序,如 Uvicorn(默认使用),HypercornDaphne

只需告诉 Flet 导出 ASGI 应用程序:

main.py
import flet as ft

def main(page: ft.Page):
page.add(ft.Text("Hello ASGI!"))

app = ft.app(main, export_asgi_app=True)

然后用 Hypercorn 运行:

hypercorn main:app --bind 0.0.0.0:8000

Web应用环境变量

Web 应用程序托管的每个方面都可以通过环境变量控制:

  • FLET_FORCE_WEB_SERVER - 设置为 true 强制运行应用程序作为 Web 应用程序。在无头 Linux 主机上自动设置。
  • FLET_SERVER_PORT - 运行应用程序的 TCP 端口。如果程序在 Linux 服务器上运行或设置了 FLET_FORCE_WEB_SERVER,则为 8000;否则为随机端口。
  • FLET_SERVER_IP - 监听 Web 应用程序的 IP 地址,例如 127.0.0.1。默认是 0.0.0.0 - 绑定到所有服务器 IP。
  • FLET_ASSETS_DIR - 应用程序 "assets" 目录的绝对路径。
  • FLET_UPLOAD_DIR - 应用程序 "upload" 目录的绝对路径。
  • FLET_MAX_UPLOAD_SIZE - 允许上传文件的最大大小,以字节为单位。如果未指定,则不受限制。
  • FLET_SECRET_KEY - 签署临时上传 URL 的密钥。
  • FLET_WEB_APP_PATH - 域名后的 URL 路径,用于托管 Web 应用程序,例如 /apps/myapp。默认是 / - 在根目录下托管应用程序。
  • FLET_SESSION_TIMEOUT - 会话的生命周期,以秒为单位。默认是 3600
  • FLET_OAUTH_STATE_TIMEOUT - 完成 OAuth Web 流程的最长允许时间,以秒为单位。默认是 600
  • FLET_WEB_RENDERER - Flutter 渲染模式:canvaskit(默认),htmlauto
  • FLET_WEB_USE_COLOR_EMOJI - 设置为 trueTrue1 以加载带有彩色表情符号的 Web 字体。
  • FLET_WEB_ROUTE_URL_STRATEGY - path(默认)或 hash
  • FLET_WEBSOCKET_HANDLER_ENDPOINT - WebSocket 处理程序的自定义路径。默认是 /ws
  • FLET_UPLOAD_HANDLER_ENDPOINT - 上传处理程序的自定义路径。默认是 /upload
  • FLET_OAUTH_CALLBACK_HANDLER_ENDPOINT - OAuth 处理程序的自定义路径。默认是 /oauth_callback

异步优先框架

Flet 现在是一个异步优先框架,这意味着你不必决定你的应用程序是完全同步还是异步,你可以在同一个应用程序中混合使用同步和异步方法。

例如,在 Flet 0.21.0 中,你可以这样编写一个应用程序:

import flet as ft
import time
import asyncio

def main(page: ft.Page):

def handler(e):
time.sleep(3)
page.add(ft.Text("Handler clicked"))

async def handler_async(e):
await asyncio.sleep(3)
page.add(ft.Text("Async handler clicked"))

page.add(
ft.ElevatedButton("Call handler", on_click=handler),
ft.ElevatedButton("Call async handler", on_click=handler_async)
)

ft.app(main)

在上面的示例中,点击一个按钮由“阻塞”处理程序处理,而点击第二个按钮调用异步处理程序。第一个处理程序在threading.Thread中运行,而第二个处理程序在asyncio.Task中运行。

此外,请注意在async def处理程序中不再需要使用await page.add_async(),而是可以使用常规的page.add()

API变更

大多数Page.<method>_async()Control.<method>_async()方法已被弃用,应使用其Page.<method>()Control.<method>()对应方法。

唯一的例外是返回结果的方法,例如Audio控制中的那些方法:在异步事件处理程序中仍然必须使用异步方法。

自定义控件 API 规范化

在这个 Flet 版本中,我们还重新审视了在 Python 中编写自定义控件的 API。

因此,UserControl类已被弃用。你只需继承具有适合你需求的布局的特定控件。

例如,Countdown自定义控件只是一个Text,可以如下实现:

import asyncio

import flet as ft

class Countdown(ft.Text):
def __init__(self, seconds):
super().__init__()
self.seconds = seconds

def did_mount(self):
self.running = True
self.page.run_task(self.update_timer)

def will_unmount(self):
self.running = False

async def update_timer(self):
while self.seconds and self.running:
mins, secs = divmod(self.seconds, 60)
self.value = "{:02d}:{:02d}".format(mins, secs)
self.update()
await asyncio.sleep(1)
self.seconds -= 1

def main(page: ft.Page):
page.add(Countdown(120), Countdown(60))

ft.app(main)

注意使用self.page.run_task(self.update_timer)启动新任务。 控件开发者还必须使用self.page.run_thread()方法在线程中启动新后台作业。

如果你想生成自己的任务或线程,Flet通过Page.loopPage.executor属性分别提供当前事件循环和线程执行器。

API变更

Control._before_build_command()Control.before_update()取代

Control.build()现在不应返回任何控件,而必须更新继承的控件属性,例如:

def build():
self.controls.append(ft.Text("Something"))

Control.did_mount_async()Control.will_unmount_async()已被弃用。请使用Control.did_mount()Control.will_unmount()

新的Cupertino控件

此Flet版本添加了更多Cupertino控件,使你的应用在iOS上更加出色:

  • CupertinoActivityIndicator
  • CupertinoActionSheet
  • CupertinoSlidingSegmentedButton
  • CupertinoSegmentedButton
  • CupertinoTimerPicker
  • CupertinoPicker
  • CupertinoDatePicker
  • CupertinoContextMenu

无障碍性改进

现在Flet已经完全实现了Semantics控件和新的SemanticsService控件。

应用生命周期更改事件

新增了 Page.on_app_lifecycle_state_change 事件,允许监听应用程序生命周期的变化。

例如,当应用变为活动状态(切换到前台)时,你现在可以使用最新信息更新UI。此事件适用于iOS、Android、所有桌面平台和Web!

以下是识别的应用程序生命周期转换:

  • SHOW
  • RESUME
  • HIDE
  • INACTIVE
  • PAUSE
  • DETACH
  • RESTART
备注

阅读有关每个生命周期状态的更多信息。

这是一个如何使用此事件的小示例:

import flet as ft

def main(page: ft.Page):

def app_lifecycle_change(e: ft.AppLifecycleStateChangeEvent):
if e.state == ft.AppLifecycleState.RESUME:
print("Update UI with fresh data!")

page.on_app_lifecycle_state_change = app_lifecycle_change
page.add(ft.Text("Hello World"))

ft.app(target=main)

Flet 0.21.0版本有一些重大变化。升级到它,测试你的应用,并让我们知道它的运行情况。加入Flet Discord服务器或在Flet GitHub讨论区创建一个新话题。

祝你愉快!