ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Flipper Zero Unleashed Firmware JS 开发:gui/loading 加载视图模块完全指南

2026/9/13 17:19:31 拓冰建站 浏览量
Flipper Zero Unleashed Firmware JS 开发:gui/loading 加载视图模块完全指南 Flipper Zero Unleashed Firmware JS 开发gui/loading 加载视图模块完全指南【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware导读本文面向 Flipper Zero Unleashed Firmware 的 JavaScript 应用开发者系统讲解gui/loading子模块的用法如何通过require(gui/loading)创建一个显示动画沙漏的加载视图并利用其抑制所有导航事件的特性在异步任务进行期间锁定界面。读完本文你将掌握 loading 视图的导入依赖顺序、创建与切换方法、无属性props的 API 设计以及它从 JS 到 C 底层的完整实现链路。Loading 视图的核心行为Loading 视图loading view是 Flipper Zero GUI 体系中一个专用于等待场景的全屏视图。它的核心行为有两点显示一个动画沙漏图标直观地向用户传达程序正在处理中请稍候抑制所有navigation事件用户按下 BACK 键也无法退出该视图从而保证异步操作在完成前不会因误触返回键而中断。这一设计在 GUI 子模块清单中有明确定位见 js_gui.md 的 Submodules 一节gui/loading — Displays an animated hourglass icon显示动画沙漏图标。模块导入与依赖顺序与所有 GUI 子模块一致使用 loading 视图前必须按照严格的依赖顺序导入模块let eventLoop require(event_loop); let gui require(gui); let loadingView require(gui/loading);gui/loading依赖gui模块而gui又依赖event_loop模块因此必须按上述顺序导入先导入event_loop再导入gui最后导入gui/loading。官方文档同时建议在深入使用本模块之前先理解 event loop 与 GUI 的基础概念View、Viewport、ViewDispatcher 等。依赖关系背后的实现依据导入顺序并非随意约定而是由固件中的插件注册机制决定的。在 application.fam 中gui插件appidjs_gui与gui/loading插件appidjs_gui__loading分别注册而 js_gui.c 的js_gui_create在创建 GUI 对象时会通过js_module_get(modules, event_loop)显式获取事件循环实例拿不到就直接返回 NULL。这印证了gui 必须先于子模块、event_loop 必须先于 gui的硬性依赖。创建与使用 Loading 视图导入后loadingView是一个 ViewFactory视图工厂。调用make()即可创建一个 Loading 视图实例let loading loadingView.make();创建好的视图由gui.viewDispatcher统一管理。通过switchTo()切换到 loading 视图后屏幕即显示动画沙漏gui.viewDispatcher.switchTo(loading);完整可运行示例官方 GUI 文档提供了一个三视图切换的完整示例见 js_gui.md 与 gui/index.d.ts其中 loading 视图正是作为沙漏屏演示项let eventLoop require(event_loop); let gui require(gui); let loadingView require(gui/loading); let submenuView require(gui/submenu); let emptyView require(gui/empty_screen); // 常见写法将所有视图集中声明在一个对象中便于管理 let views { loading: loadingView.make(), empty: emptyView.make(), demos: submenuView.makeWith({ items: [ Hourglass screen, Empty screen, Exit app, ], }), }; // 根据子菜单选择切换不同界面 eventLoop.subscribe(views.demos.chosen, function (_sub, index, gui, eventLoop, views) { if (index 0) { gui.viewDispatcher.switchTo(views.loading); } else if (index 1) { gui.viewDispatcher.switchTo(views.empty); } else if (index 2) { eventLoop.stop(); } }, gui, eventLoop, views); // 按下 BACK 键时返回选择菜单 eventLoop.subscribe(gui.viewDispatcher.navigation, function (_sub, _, gui, views) { gui.viewDispatcher.switchTo(views.demos); }, gui, views); // 启动 UI gui.viewDispatcher.switchTo(views.demos); eventLoop.run();示例中的关键点视图创建后即被 ViewDispatcher 自动登记switchTo()可随时切换eventLoop.subscribe()用于响应子菜单选中项chosen事件与导航事件主循环由eventLoop.run()驱动GUI 事件与用户输入都经由事件循环派发。View propsLoading 视图没有任何可配置属性Loading 视图是 GUI 体系中极少数零配置的视图之一不提供任何 props。这意味着调用loadingView.makeWith({...})传入属性对象时没有任何属性会被识别调用view.set(name, value)修改属性同样无效。这一点有双重证据支撑JS 适配器源码loading.c 中的视图描述符明确写着prop_cnt 0、props {}即 JS 侧可见的属性数量为零TypeScript 类型定义loading.d.ts 中type Props {}且type Child never从类型系统层面宣告该视图既没有属性也不接受任何子元素children。同时由于 Loading 视图没有 children 支持调用addChild/setChildren/resetChildren会触发 js_gui.c 中的错误处理this View cant have children。底层实现原理从 JS 到 C 的完整链路JS 适配层Loading 视图的 JS 适配器loading.c非常简洁它声明了一个JsViewDescriptor将底层 C 实现的loading_alloc、loading_free、loading_get_view三个函数与 JS 侧工厂机制绑定再通过JS_GUI_VIEW_DEF(loading, view_descriptor)宏定义见 js_gui.h注册为名为gui__loading的 JS 模块插件。该宏统一完成模块构造函数、插件描述符与入口点js_view_loading_ep的样板代码生成。C 实现层真正绘制沙漏动画的是 GUI 服务层的通用 C 模块 loading.c绘制回调loading_draw_callbackL21-L34先以白色清屏再在屏幕正中央居中偏移 24×24 的图标尺寸绘制A_Loading_24静态底图随后叠加IconAnimation动画帧形成沙漏流动的视觉效果输入回调loading_input_callbackL36-L40对任何输入事件直接return true吞掉这正是文档所述抑制所有 navigation 事件、无法用 BACK 键退出的底层实现——输入事件被消费后不会继续上抛为导航事件生命周期回调进入视图时调用icon_animation_start启动动画L42-L53退出时调用icon_animation_stop停止动画并释放资源L55-L61。从源码注释还可以看到一个易踩的坑如果 Loading 视图与多个 Stack View 配合使用进入视图时必须重新绑定动画 Update 回调view_tie_icon_animation否则回调可能被其他视图重写导致动画不刷新。典型使用场景Loading 视图最典型的应用场景是异步等待期间锁定界面等待蓝牙配对、存储读写、文件解析、网络请求等耗时操作完成在操作未完成前禁止用户按 BACK 键中断确保流程原子性操作结束后通过eventLoop订阅的结果回调或定时器用gui.viewDispatcher.switchTo(...)切换到下一个视图。一个常见模式是配合事件循环的计时器timer或外部事件源contract驱动切换进入 loading 视图后开始后台任务任务完成事件触发时再切换离开。由于 loading 视图本身没有 props也无需清理状态在需要临时占位 防止误操作的场景中是最轻量的选择。参考文档与源码索引模块官方文档js_gui__loading.mdGUI 模块总览含概念讲解与完整示例js_gui.mdJS 适配器源码loading.c视图工厂机制JS_GUI_VIEW_DEF宏js_gui.hGUI 服务层 C 实现loading.cTypeScript 类型定义loading.d.ts模块注册清单application.fam【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考