【Android】AndroidStudio编写插件超详细教程(一)

AndroidStudio插件超详细教程(一)

本教程从0开始,边探索边讲解思路,保证详细~~~写的时候发现有点长,准备分2-3次写完吧。


AndroidStudio编写插件超详细教程(一)
AndroidStudio编写插件超详细教程(二)
AndroidStudio编写插件超详细教程(三)


最近项目试了一下Android组件化架构,感觉坑还是蛮多的,首先ButterKnife就用不了了,各种R和R2文件的切换就烦死,刚开始看了下ButterKnife Zelezny插件的源码,增加了R文件的选择,感觉在组件化中还是不太好用,最后还是用回了痛苦的findViewById,正好也看了看android studio编写插件的相关知识,今天就和大家一起撸一个findViewById插件!


  • 环境配置
  • 项目目录结构
  • 配置插件信息
  • 获取资源文件名

环境配置

Android Studio是基于IntelliJ专门为Android定制的IDE,是没有办法编写IDE的插件的,所以我们首先要下载一个开发Java用的IntelliJ IDEA。具体下载过程就不赘述了,网上教程一大堆,咱们也不是专门开发Java,随便下载一个就好。

下载好打开后,我们看到了一个熟悉的页面,和android studio差不多,选择新建一个项目。左边选择IntelliJ Platform Plugin,右上方Project SDK第一次进入应该是没有配置的。
这里写图片描述
我们选择New,选择一个SDK。这里系统一般Idea的根目录,我们直接确定即可。接下来系统会让你选择一个JDK,也就是java环境,同样也会定位到相应位置,如果没有定位到,我们使用开发Android时JDK的路径就可以了。查看Android Studio中的JDK路径:
查看Android Studio中的JDK路径

配置好环境后,我们就可以愉快的编写插件啦!

项目目录结构

新建好的项目目录结构比较简单,没有什么多余的文件。大概长这样。
这里写图片描述
其中com.xxx.xxx刚创建好时是没有的,需要自己建包。

  • .idea: idea的一些配置信息。

  • out: 编译生成的一些.class文件,有点类似于android的build文件夹。

  • resources/META-INF/plugin.xml: 插件的一些描述信息,和我们接下来要写的插件操作“Action”的配置。类似android中的Manifest文件。

  • src: 这里就是我们要写代码的地方啦。

  • .iml: 项目的一些配置信息,一般不用去管,和android的.iml一样。

  • External Libraries: 这个也和android一样,时引用的第三方库。

整体看下来,编写插件代码和我们平时写android代码的时候非常类似。还是非常容易理解的。使用的语言也就是java语言,学习成本很低,但是可以开发出一些非常好玩的插件。

配置插件信息

好,各个文件的作用我们已经大概了解了,接下来,我们先来配置一下我们的插件信息,也就是配置我们的resources/META-INF/plugin.xml文件。配置文件里有很详细的英文描述。这里只简单的说一下。
这里写图片描述

  • id: 插件唯一的id。

  • name: 插件显示的名字。

  • version: 插件版本。

  • vendor: 里面分别是你的邮箱,公司网站或个人网站,公司名。

  • description: 插件的描述。

  • change-notes: 更新文档。

  • extensions defaultExtensionNs: 默认依赖的库。

  • actions: “注册”一会编写的动作Action类。

具体填写的东西展示出来是什么样子,大家可以去android studio的插件仓库中看看,对应填写相应的内容就好。如ButterKnife Zelezny填写的配置信息长这样。
这里写图片描述

获取资源文件名

好,接下来是大家最喜欢的敲代码了!其实android studio中,每个按钮都相当于一个系统写好的插件,点击这些按钮执行的动作,都是在对应的Action中写好的。我们要做的,就是给IDE添加一个我们自己的按钮,并且写一个做我们想要操作的Action。

怎么做呢?首先,我们在我们创建好的包中new一个Action。
这里写图片描述

点击后出现如下弹窗,让我们配置Action的一些信息。

这里写图片描述

其中,Action Id,Class Name就不多说了,Name为显示给用户的动作名称,Description为操作的描述。

Groups是比较重要的,他代表了我们按钮展示的位置。比如选择GenerateGroup,就是在Generate中显示(Windows中快捷键alt+insert,Mac快捷键control+enter)。还有build、code(显示在菜单栏上build、code按钮中)等等一系列Groups的位置,大家根据需要自己选择。不知道意思的网上查一下就好。
这里写图片描述
右边Actions是选择按钮位置的,First和Last分别为菜单最上方和最下方,点击Actions中的按钮,可以选择在该按钮的下方和上方。我这里模仿了ButterKnife Zelezny选择了GenerateGroup,并且放在了最下方。运行时的效果是这样的:
这里写图片描述
后面的Keyboard Shortcuts中的First和Second就是我们自定义的快捷键了,这里注意快捷键不要和其他系统的快捷键冲突。

配置好后,我们点击ok,就能看到我们新建好的类了。

public class FindViewsAction extends AnAction {
    @Override
    public void actionPerformed(AnActionEvent anActionEvent) {

    }
}

同时,我们的plugin.xml中也自动帮我们注册好了Action。在action标签中,我们还可以给action增加一个icon字段来设置按钮前面的图标。


一步一步来,Acton已经创建好了,接下来就是写我们的方法了,我们先看一下自动继承的这个AnAction类有什么我们可以用的方法。

看完我就更懵逼了。除了一个自动重写的actionPerformed大概能看出来是按钮被点击的操作外,似乎没有用的上的方法啊。AnActionEvent里也就是有个getProject方法感觉对我们有点用。
这里写图片描述

到这里,我是彻底不知道咋弄了。慢慢来,我们先来捋一捋需求。我们要做的是一键findViewById,首先要获取到光标所在的layout文件,然后读取出layout.xml文件里的所有vieiw的id,最后把再代码中生成全局的变量名,并且绑定findViewById找到的控件。

那第一步就是找到光标所在的layout.xml文件。那肯定要用到光标了。根据需求找方法,我发现anActionEvent中有一个getData方法,这个方法的参数中正好有一个DataKeys.EDITOR,这个似乎是我们想要的啊,得到之后,果然有一个光标的单词caret

@Override
public void actionPerformed(AnActionEvent anActionEvent) {
    Editor editor = anActionEvent.getData(DataKeys.EDITOR);
    if (editor != null) {
        //得到编辑器的光标类
        CaretModel caret = editor.getCaretModel();
    }
}

得到光标之后,我们应该就可以找到我们需要的资源文件了。但是,看了半天方法。。也没找到得到光标所在文件的方法。。没办法,看一下ButterKnifeZelezny的源码吧。

在源码里,我发现了PsiUtilBase.getPsiFileInEditor()这个方法。并且很多文件操作都用到了PsiFile,这个是干什么的呢?还是看一下官网吧。本人英语捉急,不过文档也比较简单,大概还是能看出点东西的。附上官网地址:IDEA插开发工具SDK文档

进入官网后,我们可以左上角搜索一下psi,然后找到psi files,看一下英文全称我们概可以了解到,这是一个表示文件结构的接口,PsiFile是一个基类,里面还有PsiJavaFileXmlFile。那我们获取xml文件中的id,要拿到的肯定是XMLFile这个类。
这里写图片描述
我们再往下翻,其中有两个标题比较重要。分别是,我们怎么得到这个类,还有我们能用这个类做什么。
这里写图片描述
这里写图片描述
我们看到三个比较重要的方法。
psiElement.getContainingFile(): Element我们都知道是元素的意思,通过这个方法,我们大概了解到,用光标获取文件中选中的词,大概率需要用到元素psiElement
FilenameIndex.getFilesByName(project, name,scope): 通过文件名获取文件,这个我们一会肯定也会用到。
psiFile.accept(new PsiRecursiveElementWalkingVisitor()…): 递归递归元素,我们获取id的时候肯定要递归xml文件的,这里IDEA已经帮我们写好了递归的方法。
正好搜索栏下面有一个PSI Elements的介绍,不需要多看,我们只看文档标出来的两个方法。
这里写图片描述
一个是anActionEvent.getData(LangDataKeys.PSI_ELEMENT),一个是psiPfile.findElementAt()

讲道理这里我们应该用第一个方法拿到实体类的,但是第一个方法打印出来的是xml文件的id,所以这里我们只能用第二个方法,根据光标位置找到元素,然后用文件名找到对应的xml文件实体。

PsiFile psiFile = anActionEvent.getData(DataKeys.PSI_FILE);
Editor editor = anActionEvent.getData(DataKeys.EDITOR);
CaretModel caret = editor.getCaretModel();
PsiElement psiElementA = file.findElementAt(offset);
//(R.layout.activity_main)由于光标在‘n’和‘)’中间的时候会打印出')'
//所以这里必须获取两个,然后进行判断。
PsiElement psiElementB = file.findElementAt(offset - 1);
//System.out.println(psiElementA.getText());
//打印一下发现确实打印出了文件名。

接下来我们判断一下这两个element哪个是正确的文件名

//getParent()可以得到元素包括'.'在内的字符串。
//getFirstChil()则可以得到整个字符串开头的字符
String firstChild=psiElementA.getParent().getFirstChild().getText();
if ("R.layout".equals(firstChild)) {
    //psiElementA正确就用A,psiElementB正确就用B。
    //这里只写伪代码了,全部代码之后给出下载。
}

至此,我们得到了xml文件的名字psiElement.getText,把名字末尾拼接上后缀名,就能得到完整的文件名了。

String name = String.format("%s.xml", psiElement.getText());

代码github地址:https://github.com/GeniusLiu/FindViewById-Plugin
这个代码只是一个小demo,应该还会更新,看到的朋友给个star呗~~~

  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值