名称: gpui-event 描述: GPUI中的事件处理和订阅。在实现事件、观察者或事件驱动模式时使用。支持自定义事件、实体观察和事件订阅,用于组件间的协调。
概述
GPUI提供事件系统以协调组件:
事件机制:
- 自定义事件:定义和发射类型安全的事件
- 观察:响应实体状态变化
- 订阅:监听来自其他实体的事件
- 全局事件:应用范围内的事件处理
快速开始
定义和发射事件
#[derive(Clone)]
enum MyEvent {
DataUpdated(String),
ActionTriggered,
}
impl MyComponent {
fn update_data(&mut self, data: String, cx: &mut Context<Self>) {
self.data = data.clone();
// 发射事件
cx.emit(MyEvent::DataUpdated(data));
cx.notify();
}
}
订阅事件
impl Listener {
fn new(source: Entity<MyComponent>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// 订阅事件
cx.subscribe(&source, |this, emitter, event: &MyEvent, cx| {
match event {
MyEvent::DataUpdated(data) => {
this.handle_update(data.clone(), cx);
}
MyEvent::ActionTriggered => {
this.handle_action(cx);
}
}
}).detach();
Self { source }
})
}
}
观察实体变化
impl Observer {
fn new(target: Entity<Target>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// 观察实体的任何变化
cx.observe(&target, |this, observed, cx| {
// 当observed.update()调用cx.notify()时被调用
println!("目标已改变");
cx.notify();
}).detach();
Self { target }
})
}
}
常见模式
1. 父-子通信
// 父实体发射事件
impl Parent {
fn notify_children(&mut self, cx: &mut Context<Self>) {
cx.emit(ParentEvent::Updated);
cx.notify();
}
}
// 子实体订阅
impl Child {
fn new(parent: Entity<Parent>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
cx.subscribe(&parent, |this, parent, event, cx| {
this.handle_parent_event(event, cx);
}).detach();
Self { parent }
})
}
}
2. 全局事件广播
struct EventBus {
listeners: Vec<WeakEntity<dyn Listener>>,
}
impl EventBus {
fn broadcast(&mut self, event: GlobalEvent, cx: &mut Context<Self>) {
self.listeners.retain(|weak| {
weak.update(cx, |listener, cx| {
listener.on_event(&event, cx);
}).is_ok()
});
}
}
3. 观察者模式
cx.observe(&entity, |this, observed, cx| {
// 响应任何状态变化
let state = observed.read(cx);
this.sync_with_state(state, cx);
}).detach();
最佳实践
✅ 分离订阅
// ✅ 分离以保持活跃
cx.subscribe(&entity, |this, source, event, cx| {
// 处理事件
}).detach();
✅ 清晰的事件类型
#[derive(Clone)]
enum AppEvent {
DataChanged { id: usize, value: String },
ActionPerformed(ActionType),
Error(String),
}
❌ 避免事件循环
// ❌ 不要创建相互订阅
entity1.subscribe(entity2) → 发射事件
entity2.subscribe(entity1) → 发射事件 → 无限循环!
参考文档
-
API 参考:参见 api-reference.md
- 事件定义、发射、订阅
- 观察、全局事件
- 订阅生命周期
-
模式:参见 patterns.md
- 事件驱动架构
- 通信模式
- 最佳实践和陷阱