流星雨模块框架文档中心

生命周期

入口类的发现规则

宿主在入口文件中按以下顺序定位你的模块类:

  1. 若定义了 MODULE = SomeClass,直接用它(必须是 JadeModule 子类,否则报错)。推荐显式声明,无歧义。
  2. 否则在入口命名空间中自动查找唯一的 JadeModule 子类;
  3. 找到 0 个 → ModuleLoadError: 入口文件中未找到 JadeModule 子类
  4. 找到多个 → ModuleLoadError: 存在多个 JadeModule 子类,请显式指定 MODULE 属性

自动查找只认写在入口文件里的类,从别处 import 进来的子类不会被误认。

python
class MyModule(JadeModule): ...

MODULE = MyModule          # 写在文件末尾即可

状态机

text
未加载 ──加载──▶ 已加载 ──启用──▶ 运行中
   ▲               ▲                 │
   │               └──────停用───────┘
   └────────── 卸载 / 版本替换 ──────┘
          (任意阶段出错 → 错误状态)
状态含义能否被别的模块调用
未加载已被宿主发现,还没导入
已加载导入完成,setup() 已执行
运行中on_enable() 已执行
错误加载或启用失败,主界面会显示原因

只有运行中的模块才响应调用,其余状态会收到"模块不可调用"错误。

生命周期钩子

钩子调用时机典型用途
setup(ctx)加载后一次注册处理器、订阅事件、读取配置
on_enable()启用时(可反复)启动后台线程、打开连接、开始推送数据
on_disable()停用时(可反复)停止线程、释放资源、清空卡片/字段
on_unload()卸载或版本替换前最终清理(多数情况下与 on_disable 相同即可)
python
import threading
from jade_framework import JadeModule


class Poller(JadeModule):
    def setup(self, ctx):
        ctx.register_handler("snapshot", self._snapshot)

    def on_enable(self):
        self._interval = float(self.ctx.config.get("interval", 2.0))
        self._stop = threading.Event()
        self._thread = threading.Thread(target=self._loop, daemon=True,
                                        name="my-poller")
        self._thread.start()

    def on_disable(self):
        self._stop.set()                       # 必须能停下来
        self._thread.join(timeout=self._interval + 5)
        self.ctx.set_card(None)                # 清卡片
        self.ctx.push_fields({})               # 清底部字段
        self.ctx.push_titlebar({})             # 清标题栏注册项

    on_unload = on_disable

几个容易踩的点

python
# 定时循环的标准写法:Event.wait 能被立刻唤醒
def _loop(self):
    while not self._stop.is_set():
        try:
            self._poll()
        except Exception as e:
            self.ctx.log.warning("轮询异常: %s", e)   # 记日志,不退出
        self._stop.wait(self._interval)