当前位置: 首页 > 科技观察

写一个IDEA插件:事件监听

时间:2023-03-20 15:19:37 科技观察

事件监听,我们最熟悉的就是在开发APP的时候,监听按钮点击事件,手指触摸和移动事件,网络状态事件等,事件监听大多是通过观察者模式。首先,API调用者不需要知道后台是如何检测到网络状态不可用的,只需要向系统注册一个监听器即可。当网络状态发生变化时,系统回调监听器。.本文内容:项目或模块事件监控:当某个模块或整个项目发生变化时,通过事件监控做出反应,例如在项目中添加模块或删除模块;文件编辑事件监听:在Java代码文件编辑时,可以通过事件监听知道是哪个类的代码发生了变化。这时候后台可以刷新一些数据缓存;如何监控项目或模块变更事件,首先是项目级的事件监控。添加项目管理事件监听器,需要实现ProjectManagerListener接口,该接口有四个方法,源码如下。publicinterfaceProjectManagerListenerextendsEventListener{defaultvoidprojectOpened(@NotNullProjectproject){}defaultvoidprojectClosed(@NotNullProjectproject){}defaultvoidprojectClosing(@NotNullProjectproject){}defaultvoidprojectClosingBeforeSave(@NotNullProjectproject){}}projectOpened:该方法在项目打开时;projectClosingBeforeSave:在关闭项目时,开始保存项目前回调,或调用FileDocumentManager#saveAllDocuments方法保存所有文件前回调;projectClosing:在projectClosingBeforeSave方法之后回调;projectClosed:与projectClosing的区别在于projectClosed是在项目已经关闭的时候回调的,在ProjectManagerImpl中#closeProject方法是在执行到最后一行代码的时候调用的。有了项目管理事件监听器之后,我们如何注册监听器呢?有两种方法,一种是通过代码注册,另一种是在plugin.xml插件配置文件中注册。代码注册可以调用ProjectManager.getInstance().addProjectManagerListener();方法注册,但是这种注册方法有一个缺点,就是无法监听项目打开事件,不会调用projectOpened方法。当我们可以调用这个方法Listener的时候应该是注册好了,项目才真正打开。因此,我们只能通过修改plugin.xml配置文件来注册项目管理监听器。配置代码如下:topic:填写事件主题,类似于消息中间件中的Topic,只是这里填写的是事件监听器的接口类名??;class:添加接口的实现类名;当我们为IDEA注册了一个自定义的项目管理事件监听器后,我们可以通过项目管理事件监听器来注册其他的事件监听器,比如注册一个模块来监听事件,因为模块的事件是在项目打开后触发的。会触发。因此,可以在projectOpened方法中注册任何其他事件侦听器。注册模块事件监听器的代码如下:project.getMessageBus().connect().subscribe(ProjectTopics.MODULES,newModuleListener(){});subscribe方法需要两个参数:topic:主题,可选值见ProjectTopics类的源码,有PROJECT_ROOTS和MODULES;handler:事件处理器,监听器,当topic为MODULES时,需要传入一个ModuleListener;ModuleListener接口的定义如下:Module>modules,@NotNullFunctionoldNameProvider){}}moduleveAdded:添加模块时调用;embefore:ModuleRule在被移除之前调用;moduleRemoved:移除模块时调用;modulesRenamed:模块修改名称时调用;如何监听文件编辑事件通过前面两篇文章的学习,我们已经了解了什么是PSI,知道一个文件对应一个PsiFile,一个PsiFile本身也是一个PsiElement,由很多PsiElement组成,每个PsiElement组成PsiElement也可以有子PsiElements。因此,监听文件变化事件实际上就是监听PSI树结构变化事件,我们需要通过PsiManager注册PsiTreeChangeListener,代码如下。PsiManager.getInstance(project).addPsiTreeChangeListener(newPsiTreeChangeListener(){//.....},FILES::clear);至于注册时机,看情况,可以在Service初始化时注册,也可以在AnAction触发时注册,也可以在projectOpened事件方法中注册。PsiTreeChangeListener接口定义了很多方法,可以分为两种事件,一种是事件前,一种是事件后。接口源码如下。publicinterfacePsiTreeChangeListenerextendsEventListener{voidbeforeChildAddition(@NotNullPsiTreeChangeEventevent);voidbeforeChildRemoval(@NotNullPsiTreeChangeEventevent);voidbeforeChildReplacement(@NotNullPsiTreeChangeEventevent);voidbeforeChildMovement(@NotNullPsiTreeChangeEventevent);voidbeforeChildrenChange(@NotNullPsiTreeChangeEventevent);voidbeforePropertyChange(@NotNullPsiTreeChangeEventevent);voidchildAdded(@NotNullPsiTreeChangeEventevent);voidchildRemoved(@NotNullPsiTreeChangeEventevent);voidchildReplaced(@NotNullPsiTreeChangeEventevent);voidchildrenChanged(@NotNullPsiTreeChangeEventevent);voidchildMoved(@NotNullPsiTreeChangeEventevent);voidpropertyChanged(@NotNullPsiTreeChangeEventevent);}childrenChanged:子元元件更改时间被调用;childReplaced:子元素被替换时被调用,触发childReplaced事件也会伴随着childrenChanged事件;childAdded:添加子元素时调用,childAdded事件触发时,还会伴随childReplaced、childrenChanged或事件;childRemoved:移除子元素时调用,触发childRemoved事件。也会伴随着child取代,childrenChan事件;propertyChanged:当属性发生变化时调用,比如修改文件名;暂且写上一篇《写一个IDEA插件》系列,因为对这方面感兴趣的读者可能比对汇编语言感兴趣的读者要少。其实这几篇文章的分析也是笔者在写插件的过程中认为非常重要的一些知识点。当然,还有很多没有分享出来。没有继续写下去的动力了。参考:intellij-platform-plugin-template的项目管理监听器注册:https://sourcegraph.com/github.com/JetBrains/intellij-platform-plugin-template@main/-/blob/src/main/resources/META-INF/plugin.xml#L17:55接收项目结构变更通知:https://jetbrains.org/intellij/sdk/docs/reference_guide/project_model/project.html?search=projectClosingBeforeSave本文转载自微信公众号“爪哇艺术”,可以通过以下二维码关注。转载本文请联系爪哇艺术公众号。