Flet 移动端更新
本文是几个月前发布的Flet 移动端战略的延续。
我们最初在移动设备上运行 Flet 的方法是服务器驱动的 UI(SDUI)。尽管 SDUI 有其自身的优点(比如绕过应用商店进行应用更新),但它并不适用于所有情况,需要 Web 服务器来托管应用程序的 Python 部分,并且由此增加了响应延迟,这对于需要几乎即时 UI 响应的用户操作(如绘图应用程序)并不理想。
我一直在思考如何将 Python 运行时嵌入到 Flutter iOS 或 Android 应用程序中以运行用户的 Python 程序。毫无疑问,从技术上讲是可行的,因为 Kivy 和 BeeWare 项目已经实现了这一点。
当前的 Flet 架构
当前 Flet 桌面应用程序的架构如下图所示:
在桌面上运行 Flet 程序涉及到三个应用程序(进程)协同工作:
- Python 运行时 (
python3
) - 运行您的 Python 脚本的 Python 解释器。这是您从命令行启动的内容。Python 启动 Fletd 服务器并通过 WebSockets 连接到它。 - Fletd 服务器 (
fletd
) - 使用 Go 编写的 Flet Web 服务器,监听一个 TCP 端口。Fletd 保存所有用户会话的状态(对于桌面应用程序只有一个会话),并在 Python 程序和 Flet 客户端之间分发页面更新和用户生成的事件。 - Flet 客户端 (
flet
) - 使用 Flutter 编写的桌面应用程序,在本地操作系统窗口中显示 UI。Flet 客户端通过 WebSockets 连接到 Fletd 服务器。
上述架构对于 Flet Web 应用程序效果良好,因为 Web 服务器是必要的一部分,但对于桌面应用程序来说似乎是多余的:
- 如果所有三个进程在同一台计算机上运行,WebSockets 可以用消息传递队列或命名管道替代,减少开销。
- 对于只有一个用户会话且 UI 状态永久存储在 Flet 桌面客户端中且从不“重新加载”的桌面应用程序来说,Fletd 服务器没有多大意义。
新的 Flet 桌面架构
通过将 Fletd 替换为用 Python 编写的“存根”,并通过 sockets(Windows)和 named pipes(macOS 和 Linux)与 Flet 桌面客户端通信,可以简化 Flet 桌面应用程序的架构:
Flet 移动架构
移动应用程序在非常严格的环境中运行,有许多限制。例如,在 iOS 上,应用程序无法生成新进程。换句话说,Flet Flutter 应用程序不能简单地启动“python.exe”并将您的脚本作为参数传递。
幸运的是,Python 可以被嵌入到另一个应用程序作为 C 库,并且 Dart(Flutter 应用程序编写的语言)允许通过FFI(外部函数接口)调用 C 库。
此外,尽管 Android 允许动态链接库的加载,但 iOS 要求所有库都静态链接到应用程序可执行文件中。这篇文章更详细地介绍了 Dart FFI,如果您感兴趣的话。
Flet 移动架构可能如下所示:
Python 运行时将与 Flutter 客户端应用程序静态或动态链接,并通过 FFI 和/或具名管道进行调用。
尽管在移动设备上运行 Python 存在一些限制。最重要的限制之一是要求使用适用于移动设备 ARM64 架构的“纯” Python 模块或使用专门为移动设备编译的具有本机代码的模块。
异步支持
Asyncio 是 Python 3 的一部分,我们开始看到越来越多的库开始适应 async/await 编程模型,这对于 I/O 绑定和 UI 逻辑更有效。
目前,Flet在新线程中生成所有UI事件处理程序,而且随处可见threading.sleep()
调用阻塞线程,仅仅是为了进行一些UI动画。所有这些看起来都很费资源。
使用异步库的异步代码 是可能的,但看起来很别扭且效率低下,因为它让 CPU 忙于等待异步方法完成。因此,我们希望 Flet 应用程序能够对异步代码提供一流支持。
异步/等待模型是在单个线程中切换任务的状态机。通过采用异步方式,Flet 将能够利用流处理套接字服务器,并使用异步WebSockets 库库。它将能够在单个 Flet 应用程序中同时使用同步和异步事件处理程序,而无需任何妥协或黑客手段。
更令人兴奋的是,异步 Flet 将能够完全在Pyodide内运行,Pyodide 是基于 WebAssembly(WASM)的 Python 发行版。WebAssembly 尚无多线程支持,因此在单个线程中运行是必须的。想象一下,具有真正离线 Flet PWA 的 Flet Web 应用程序,它不需要 Web 服务器来运行 Python 代码!
开发计划
我们将在几个迭代中压缩上面的范围:
- 支持异步API,并使用异步WebSockets库。与Go中的相同Fletd一起工作。
- 使用Python的Fletd服务器("存根")与桌面应用程序一起使用。
- 将Python与Fletd“存根”和用户程序嵌入iOS中。
- 将Python嵌入Android中。
- 为iOS和Android打包移动应用程序。
🙏 我正在寻求社区在开发 Flutter 和 Python 在 iOS 和 Android 之间的 C/C++/本机代码集成方面的帮助。这可以是免费帮助或有偿工作 - 如果您有兴趣,请告诉我!
请访问 Discord 讨论该计划,提供帮助,提出问题!