前言
做IDEA插件,发现一个数据变动好几处需要配合改动。感觉好麻烦,总不能每次改动都在修改数据的地方加上处理吧。想起来有个监听器模式,想必IDEA肯定也是有相应机制的。官网手册➹
一、IDEA的消息传递简介
事件组成元素:
- TOPIC:消息主题
- Listener:消息监听器
消息广播:ProjectBus是ApplicationBus的子集,每个topic都可以有多个监听器; - 消息通过ApplicationBus发送到topic1;
- Handler1收到消息通知;
- 消息传递给ProjectBus中topic1的订阅者(handler2和handler3);
二、发布消息与处理消息
- 创建Listener
public interface DateRefreshListener {
void refresh(String date,Project fireProject);
}
- 创建Publisher及其Topic
public class DateRefreshMessagePublisher {
public static final Topic<DateRefreshListener> TOPIC = new Topic<>("date refresh events", DateRefreshListener.class);
public static DateRefreshMessagePublisher getInstance(Project project) {
return (DateRefreshMessagePublisher) project.getPicoContainer().getComponentInstanceOfType(DateRefreshMessagePublisher.class);
}
/**
* 推送刷新事件
*/
public void fireDateRefreshExecute(String date, Project project) {
getPublisher(project).refresh(date, project);
}
@NotNull
private static DateRefreshListener getPublisher(Project project) {
return project.getMessageBus().syncPublisher(TOPIC);
}
}
- 在Plugin.xml注册Service、Listener
public class DateRefreshNotifyListener implements DateRefreshListener {
@Override
public void refresh(String date, Project fireProject) {
Notification notify = NotifyGroupConstants.NOTIFICATION_GROUP
.createNotification("通过plugin.xml定义的-Listener给" + fireProject.getName() + "发通知" + date, NotificationType.INFORMATION);
notify.notify(fireProject);
}
}
<extensions defaultExtensionNs="com.intellij">
<projectService serviceImplementation="org.intellij.sdk.service.DateRefreshNotifyListener"/>
<projectService serviceImplementation="org.intellij.sdk.listener.DateRefreshMessagePublisher"/>
<toolWindow id="Sample Calendar" secondary="true" icon="AllIcons.General.Modified" anchor="right"
factoryClass="org.intellij.sdk.toolWindow.MyToolWindowFactory"/>
</extensions>
<projectListeners>
<listener class="org.intellij.sdk.service.DateRefreshNotifyListener"
topic="org.intellij.sdk.listener.DateRefreshListener"/>
</projectListeners>
<idea-version since-build="193.0"/>
- 【演示用】在toolwindow创建时,增加监听方法
public class MyToolWindowFactory implements ToolWindowFactory {
AtomicBoolean icon = new AtomicBoolean(true);
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
MyToolWindow myToolWindow = new MyToolWindow(toolWindow, project);
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
Content content = contentFactory.createContent(myToolWindow.getContent(), "", false);
toolWindow.getContentManager().addContent(content);
project.getMessageBus().connect().subscribe(DateRefreshMessagePublisher.TOPIC, (date, fireProject) -> {
if (icon.get()) {
toolWindow.setIcon(AllIcons.Actions.Cancel);
icon.set(false);
} else {
toolWindow.setIcon(AllIcons.Actions.Refresh);
icon.set(true);
}
Notification notify = NotifyGroupConstants.NOTIFICATION_GROUP
.createNotification("修改toolWindow图标的同时,给" + fireProject.getName() + "发通知" + date, NotificationType.INFORMATION);
notify.notify(fireProject);
});
}
}