拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Flet 1.0 Alpha 架构重写深度解读:声明式 UI、Services 与全栈重构之路

Flet 1.0 Alpha 架构重写深度解读声明式 UI、Services 与全栈重构之路【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/fletFlet 是一个仅用 Python 即可构建实时 Web、桌面与移动应用的跨平台框架。本文基于官方博客对 Flet 1.0 Alphav0.70 开发版的技术公告结合当前仓库源码系统梳理这次从零重写带来的核心变化声明式编程模型、自动刷新Auto-update、Services 服务机制、WASM 全量支持、离线模式、全新扩展 API 以及以二进制协议为底座的架构升级。读完本文你将掌握 Flet 1.0 的新编程范式、关键 API 的迁移方式、破坏性变更清单以及如何在全新虚拟环境中安装体验这一技术预览版。为什么需要 1.0从 Pglet 继承到彻底重写Flet 1.0 的发布不只是版本号的变化它代表了项目对稳定性、成熟度与长期愿景的承诺。早期的 Flet 继承了 Pglet一个面向多语言支持的 Web 框架的设计决策但随着 Flet 演进为以 Python 为中心的跨平台应用框架Web、桌面、移动三端旧的架构带来了技术债、架构错配与日益增长的复杂度。官方博客给出的判断很直接与其在裂缝上打补丁不如在 1.0 之前、用户基数尚可控时推倒重来。经过近五个月的工作Flet 1.0 Alpha 作为技术预览正式发布——它是一次完整的重新架构re-architecture而不只是下一个增量版本。核心新特性一览Flet 1.0 引入的变更可归纳为七大类既有体验改进也有破坏性变更但都围绕更快、更灵活的开发者体验展开声明式Declarative构建方式——与传统的命令式imperative风格并存可混用自动更新Auto-update——事件处理器执行完毕后页面自动刷新Services 服务——持久化的非 UI 组件可在 UI 重建与导航切换中存活Audio、FilePicker、Clipboard等既有控件被重写为服务Web 应用完全支持 WASM——现代浏览器上更快的下载与性能Web 应用离线模式no-CDN——Flutter 资源与 Pyodide 随应用一起打包将 Flet 应用嵌入已有网页——在任意网页的 HTML 元素中渲染 Flet 应用增强的 Extensions API——可随控件一起导出服务并为未来自定义启动画面、加载画面预留扩展点。声明式编程模型与命令式混用的新范式Flet 1.0 引入声明式/响应式的 UI 构建方式开发者可以在同一个应用中混合使用命令式与声明式两种模式。声明式的核心载体是ft.ControlBuilder——它接收一个状态对象和一个根据状态构建控件的函数当状态变化时自动重建对应 UI 子树。博客给出的基础声明式应用示例计数器from dataclasses import dataclass import flet as ft dataclass class AppState: count: int def increment(self): self.count 1 def main(page: ft.Page): state AppState(count0) page.floating_action_button ft.FloatingActionButton( iconft.Icons.ADD, on_clickstate.increment ) page.add( ft.ControlBuilder( state, lambda state: ft.SafeArea( ft.Container( ft.Text(valuef{state.count}, size50), alignmentft.Alignment.center(), ), expandTrue, ), expandTrue, ) ) ft.run(main)可以看到AppState是一个普通 dataclasson_click直接绑定状态方法ControlBuilder将状态与如何渲染状态的 lambda 绑定在一起。仓库中声明式编程的支撑不止于ControlBuilder——在 components 目录 下还提供了use_state、use_effect、use_ref、use_memo等 hooks见 components/hooks以及Observable、Memo等响应式原语说明 1.0 将响应式 UI作为一等公民来建设。官方还提供了更多声明式示例包括编辑表单edit-form、带yield的进度条progress-with-yield以及响应式 ToDo 应用均可作为学习参考。自动更新告别手写update()在 Flet 1.0 中Control.update()会在事件处理器方法执行完毕后被自动调用绝大多数应用不再需要显式调用update()。对于长时间运行的事件处理器可用yield主动让出控制权以刷新 UI例如async def button_click(): progress.value Something started yield await asyncio.sleep(3) progress.value Something finishedyield相当于刷新点执行到yield时把当前状态同步到前端后续代码继续异步执行从而避免界面卡死或长时间无反馈。Services跨页面存活的非 UI 组件Service 是 Flet 1.0 引入的持久化、非可视化控件能够在页面更新和导航切换中存活。Service 实例必须加入page.services列表才能生效。以下控件已被重写为服务属破坏性变更Audioflet-audio 扩展AudioRecorderflet-audio-recorder 扩展FilePickerFlashlightflet-flashlight 扩展Geolocatorflet-geolocator 扩展HapticFeedbackInterstitialAdflet-ads 扩展PermissionHandlerflet-permission-handler 扩展SemanticsServiceShakeDetector在仓库源码中服务有独立的归属目录 controls/services其中可以看到clipboard.py、file_picker.py、haptic_feedback.py、semantics_service.py、shake_detector.py、storage_paths.py等服务实现并统一继承自Service基类见 service.py。服务化设计的核心价值在于这类组件往往承载系统级能力剪贴板、文件选择、传感器其生命周期不应跟随某个页面视图的销毁而终止。WebAssembly 支持默认启用Flet 1.0 的 Web 应用在受支持的浏览器上默认使用 WebAssemblyWASM。内置的 Flet Web 客户端以及通过flet build web构建的应用现在会同时产出两种目标Dart2JS以 CanvasKit 作为渲染器WebAssembly以 SKWASM 作为渲染器。这意味着现代浏览器可以获得更快的下载速度与更好的运行性能同时保留了兼容旧浏览器的 JS 回退路径。Web 应用离线模式no-CDNFlet 1.0 提供 no-CDN 模式将以下资源与应用一同打包而不是从外部 CDN 加载CanvasKitSkWASMPyodide字体Fonts启用方式有三种运行时在ft.run()中传参这是新的ft.run()调用ft.run(main, no_cdnTrue)设置环境变量FLET_WEB_NO_CDN值为1、true或yes构建时使用flet build的--no-cdn参数。在仓库的 app.py 中可以看到ft.run()的签名确实新增了no_cdn: Optional[bool] False参数其 docstring 明确说明其作用是不从 CDN 加载 CanvasKit、Pyodide 或字体。嵌入已有网页多视图渲染Flet 1.0 支持将 Flet Web 应用嵌入到现有网页中的任意 HTML 元素并且可以在不同 HTML 元素中渲染同一个应用的多个视图。这正是Page拆分为Page与PageView的动机所在见下文Page 拆分小节。增强的 Extensions API从方法到类新版扩展 API 允许 Flutter 包同时导出**控件control与服务service**两类组件。技术上扩展从方法演变为类为后续增加自定义启动画面、加载画面等钩子预留了空间。以flet-ads扩展为例Flet v0 时代的写法是单个createControl方法import package:flet/flet.dart; import package:google_mobile_ads/google_mobile_ads.dart; import banner.dart; import interstitial.dart; CreateControlFactory createControl (CreateControlArgs args) { switch (args.control.type) { case banner_ad: return BannerAdControl( parent: args.parent, control: args.control, backend: args.backend); case interstitial_ad: return InterstitialAdControl( parent: args.parent, control: args.control, backend: args.backend); default: return null; } }; void ensureInitialized() { if (isMobilePlatform()) { MobileAds.instance.initialize(); } }而 Flet v1 中扩展是一个继承FletExtension的类同时实现createService与createWidget两个方法import package:flet/flet.dart; import package:flutter/cupertino.dart; import package:google_mobile_ads/google_mobile_ads.dart; import banner.dart; import interstitial.dart; class Extension extends FletExtension { override void ensureInitialized() { if (isMobilePlatform()) { MobileAds.instance.initialize(); } } override FletService? createService(Control control) { switch (control.type) { case InterstitialAd: return InterstitialAdService(control: control); default: return null; } } override Widget? createWidget(Key? key, Control control) { switch (control.type) { case BannerAd: return BannerAdControl(control: control); default: return null; } } }这一变更属于破坏性变更。在仓库 Dart 端扩展基类的定义位于 packages/flet/lib/src/flet_extension.dart服务绑定机制见 packages/flet/lib/src/services/service_binding.dart可以看到服务生命周期管理已深度融入 Flet 客户端运行时。其他改进与 API 变化ft.run()新增before_main钩子ft.run()新增before_main参数。它是在 Flutter 客户端开始发送事件之前、可靠地配置页面级事件处理器的钩子接受一个参数page: ft.Pagedef config(page: ft.Page): page.on_resize lambda e: print(Page resized!) def main(page: ft.Page): page.add(ft.Text(Hello!)) ft.run(main, before_mainconfig)仓库中 app.py 对before_main的定义为在Page创建之后、main之前调用并贯穿__run_pyodide、FastAPI 会话创建等多个运行路径说明该钩子在 WebPyodide、桌面本地 socket与服务器端都统一生效。page.storage_paths多平台存储路径 API新的page.storage_paths基于 Flutter 的 path_provider提供跨平台查找文件系统常用位置的能力全部为 async 方法get_application_cache_directory_async(self) - str get_application_documents_directory_async(self) - str get_application_support_directory_async(self) - str get_downloads_directory_async(self) - Optional[str] get_external_cache_directories_async(self) - Optional[List[str]] get_external_storage_directories_async(self) - Optional[List[str]] get_library_directory_async(self) - str get_external_cache_directory_async(self) - Optional[str] get_temporary_directory_async(self) - str get_console_log_filename_async(self) - str该 API 在 Python 端实现为StoragePaths服务类定义于 controls/services/storage_paths.py并在init.py 中公开导出。事件处理器可以省略e参数事件处理器现在可以省略e参数以下写法都合法button_1.on_click lambda: print(Clicked!) button_2.on_click lambda e: print(Clicked!, e)普通函数同理def increment(): print(Increment clicked) inc_btn.on_click incrementControl.before_event(e)钩子该方法会在任何事件处理器被调用之前执行。它接收一个ControlEvent实例返回True或False返回False将取消该事件处理器。Page类中的示例实现def before_event(self, e: ControlEvent): if isinstance(e, RouteChangeEvent): if self.route e.route: return False self.query() return super().before_event(e)这里对路由事件做了去重路由未变化则取消事件并顺便刷新查询字符串是一个典型的事件前置拦截与副作用注入场景。ft.context.page随处可用现在可以在 Flet 程序的任何位置获取当前Page实例的引用无需再层层传递 page 对象大幅简化了工具函数与组件库的编写。新架构一次地基级重写Flet 1.0 的架构重写旨在解决技术债、提升可维护性并释放长期性能与灵活性。博客与源码共同印证了以下关键架构决策Python 控件实现简化为 dataclass控件现在以 Pythondataclass实现带来构造函数自动生成原生支持默认值、类型注解与字段校验不再需要手工进行str/JSON转换无缝支持复杂属性类型嵌套 dataclass、枚举等。这显著减少了样板代码新增控件的成本趋近于零维护。强类型与 IDE 支持事件处理器强类型化兼顾运行时安全与开发体验所有控件包含docstrings可基于 Docusaurus 自动生成丰富的 API 文档这也解释了 1.0 Roadmap 中文档由源码生成的计划。更智能的 UI Diffing新的diffing 算法驱动 UI 树的增量更新同时针对命令式与声明式两种编程风格做了优化带来更快的重建与更少的无谓重绘。Dart 运行时现代化用InheritedWidget Provider取代旧的 Redux 状态管理Dart 端内部控制层级现在与 Python 控件树一一对应遍历与更新更高效。二进制协议用 MessagePack 取代 JSON新的**二进制序列化协议MessagePack**取代基于 JSON 的消息格式显著降低网络传输体积传输二进制数据如图片、文件不再需要 base64 编码Dart 端控件属性名与 Python 端完全一致跨运行时调试与扩展更容易。破坏性变更清单Flet 1.0 是主版本发布包含大量破坏性变更。官方维护了一份已知破坏性变更的清单issue #5238发现新问题可提交 issue 或 discussion。以下是公告中最具影响的变更摘要单线程异步 UI 模型Flet 1.0 采用类似 JavaScript / Flutter 的单线程异步 UI 模型使并发行为更可预测也更适合浏览器与移动平台time.sleep()等阻塞调用会冻结 UI应改用async def事件处理器 await asyncio.sleep()尽可能切换到 async API对于 CPU 密集型任务用asyncio.to_thread(...)卸载到线程。控件方法全部异步化所有控件的 getter/setter 方法现在是异步的不返回结果的方法提供 fire-and-forget 的同步包装。ft.run()取代旧的调用方式target参数更名为main其余参数保持不变并新增before_main见上文。Page拆分为Page与PageView为支持多视图嵌入而拆分。如果继续使用page实例的方法与属性这本身不算破坏性变更。对话框用show_dialog/pop_dialog要显示对话框、banner、snack bar、drawer 或类似弹层控件改用page.show_dialog(dialog_control)关闭最顶层的弹层使用page.pop_dialog()取代旧的page.open()。Drawer移除page.drawer与page.end_drawer改用NavigationDrawer.position属性再通过page.show_dialog()显示抽屉。官方提示未来可能为修复顶部菜单图标的显示而重新引入该 API。FilePicker 服务化与异步化FilePicker 现在是服务必须加入page.services列表。其 API 重做为直接返回对话框结果的异步方法不再依赖 result 事件处理器files: list[FilePickerFile] await file_picker.pick_files_async(allow_multipleTrue) file_name: str await file_picker.save_file_async() dir_name: str await file_picker.get_directory_path_async()仓库中服务化后的实现位于 controls/services/file_picker.py。Clipboard迁移到page.clipboard原page.set_clipboard()→page.clipboard.set_async()原page.get_clipboard()→page.clipboard.get_async()Client storage 更名Client storage 更名为 Shared Preferencespage.client_storage属性更名为page.shared_preferences。Scrollables属性更名可滚动控件中的on_scroll_interval属性更名为scroll_interval。按钮text改为content所有按钮不再有text属性统一使用content。Charts 独立成包图表控件已迁移到独立的flet-charts包。控件 ID 变为整数e.target现在是数字而不是字符串。如何安装体验 Flet 1.0 AlphaFlet 1.0 Alpha 以0.70.0.devXXXX版本号发布在 PyPI 上。版本命名说明今后 Flet 1.0 称为v1Flet 0.x 称为v0仓库main分支对应 Flet 1.0v0分支对应 Flet 0.x。注意请务必在全新的虚拟环境中安装 Flet 预发布版本避免与 v0 系列污染。使用 pip 安装pip install --pre flet[all]0.70.0.dev0或使用 uvuv add flet[all]0.70.0.dev0 --prereleaseallow也可以在项目依赖中直接声明flet 0.70.0.dev0。让flet build正常工作要使用flet build构建 Flet 1.0 Alpha 应用需要在pyproject.toml的dependencies中指定 flet 与所有扩展包的精确版本dependencies[ flet 0.70.0.dev0, flet-audio 0.2.0.dev0, flet-video 0.2.0.dev0, ... ]版本约定Flet v1 的扩展版本为0.2.x及以上Flet v0 的扩展版本为0.1.x。通往 Flet 1.0 的路线图Flet 0.70Flet 1.0 Alpha——本版本自动生成的文档尚未包含可能发布 0.71、0.72、0.73 等小版本修复问题Flet 0.80Flet 1.0 Beta——源码生成的文档就绪所有扩展可用并有文档集成测试可用Flet 0.90Flet 1.0 RC——官网落地页更新API 完整并冻结Flet 1.0Flet 1.0 RTM——正式发布。结语Flet 1.0 Alpha 标志着框架新篇章的开始以性能、可维护性与开发者体验为核心带来了精简的架构、强大的声明式编程模型与重新设计的扩展系统同时为稳定、可扩展的 1.0 正式版打下基础。需要强调的是这是一个技术预览版尚不适合生产环境。官方邀请开发者安装体验、提交反馈共同塑造 Flet 的未来。如果你正在评估将 Flet 用于正式项目建议在独立虚拟环境中试用 v1 分支并对照本文的破坏性变更清单规划迁移路径。【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门