Android Studio Plugin 插件开发教程(二) —— 插件开发中的一些基础对象概念

Posted by boredream on August 28, 2017

先树立一个概念,AS里项目的一切都可以视为对象 比如整个项目,项目里的每个文件,文件里的每个方法、每行语句等等都是一个对象 我们插件SDK的开发,大部分就是针对这一个个的对象进行分析修改

如何获取到这些对象呢? 作为整个插件的入口,Action类中会自动复写一个方法,我们可以通过方法参数ActionEvent获取各种需要的对象 回到上一章的例子中,之前的例子代码如下 可以看到用ActionEvent对象获取到了project项目对象,然后利用它去创建了一个对话框进行交互

1
2
3
4
5
6
7
8
9
10
11
12
13
public class DatabaseGeneratorAction extends AnAction {
    @Override
    public void actionPerformed(AnActionEvent e) {
        Project project = e.getData(PlatformDataKeys.PROJECT);
        String txt = Messages.showInputDialog(project,
                "What is your name?",
                "Input your name",
                Messages.getQuestionIcon());
        Messages.showMessageDialog(project,
                "Hello, " + txt + "!\n I am glad to see you.", "Information",
                Messages.getInformationIcon());
    }
}

同理还可以用这个方法获取其他对象 e.getData(PlatformDataKeys.XXX);

除了Project还有其他各种对象,以及各种获取对象的方法,下面介绍几个主要的

Virtual File

可以当做Java开发中的File对象理解,概念比较类似 获取方法

  • From an action: e.getData(PlatformDataKeys.VIRTUAL_FILE).
  • From a path in the local file system: LocalFileSystem.getInstance().findFileByIoFile()
  • From a PSI file: psiFile.getVirtualFile() (may return null if the PSI file exists only in memory)
  • From a document: FileDocumentManager.getInstance().getFile() 用处 传统的文件操作方法这个对象都支持,比如获取文件内容,重命名,移动,删除等

初次之外还有一个File类型

PSI File

PSI系统下的一个文件类 获取方法

  • From an action: e.getData(LangDataKeys.PSI_FILE).
  • From a VirtualFile: PsiManager.getInstance(project).findFile()
  • From a Document: PsiDocumentManager.getInstance(project).getPsiFile()
  • From an element inside the file: psiElement.getContainingFile()To find files with a specific name anywhere in the project, use FilenameIndex.getFilesByName(project, name, scope)

用处 作为PSI系统中的一个元素,可以使用PSI Element的各种具体方法

Virtual File 和 PSI File 的区别

如果学过Dom和Parse解析就更好理解了,Virtual File就是xml文件本身的一个抽象对象 而PSI File就是这个xml文件解析成的Document对象,虽然也是“文件”,但是特殊封装过的~ PSI系统和xml解析很像,也有元素的概念,然后有各种具体的元素节点类型,比如PsiMethod啊,PsiClass啊等等

PSI Element

下面具体介绍一下PSI Element,这个也是我们在插件开发中最常打交道的东西 获取方法

  • From an action: e.getData(LangDataKeys.PSI_ELEMENT).
  • From a file by offset: PsiFile.findElementAt().
  • By iterating through a PSI file: using a PsiRecursiveElementWalkingVisitor.
  • By resolving a reference: PsiReference.resolve()

基础对象概念简单介绍到这里,下面利用已经学习的内容写个小Demo Action创建略过,参考上一篇 通过ActionEvent的getData方法,传入对应KEY获取PsiFile 然后遍历PsiFile文件下所有的子级元素,打印出来(日志显示在开发插件的IDE的控制台) 注意,这个直接获取的PsiFile默认为当前我们当前所选的文件

1
2
3
4
5
6
@Override
public void actionPerformed(AnActionEvent e) {
    PsiFile file = e.getData(PlatformDataKeys.PSI_FILE);
    for (PsiElement psiElement : file.getChildren()) {
        System.out.println(psiElement);
    }

代码run起来 运行起来的IDE我们新建一个Android Project,默认主页面代码如下 plugin17

然后 Code Database Generate 调用我们的插件

在插件开发的IDE打印台就可以看到输出的日志为

PsiPackageStatement:com.boredream.plugindemo PsiWhiteSpace PsiImportList PsiWhiteSpace PsiClass:MainActivity PsiWhiteSpace

从结果可以看出来,把MainActivity文件下所有的子级Element都列出来了(只遍历直接子级) 看名字就能知道意思,PsiPackageStatement是包名语句,PsiImportList是导包列表,PsiClass是类。。。

不同的Element有自己对应的方法,比如PsiClass就和Java中的Class类似,可以获取Field、Method等, 之后就可以根据自己的需要处理具体逻辑了

下一章,我们就会开始自动生成数据库插件代码的编写实战~