Android Studio插件开发之-生成一个类文件

367 阅读2分钟
最终效果

Filmage 2022-01-09_150454.gif

可以自定义一个Android Studio插件,帮我们自动生成一些类文件。

  • 第一步 选用IntelliJ IDEA开发工具。
  • 创建一个插件项目,项目类型选择IntelliJ Platform Plugin。然后点击next,输入项目名称,选择项目地址,然后点击finish创建即可。

image.png

  • 配置SDK 在File -> Project Structure中配置## IntelliJ Platform SDK

image.png

  • 项目结构说明 plugin.xml为插件的管理文件,其中有插件的id、名称以及版本以及菜单信息。 image.png
<idea-plugin>
  <!-- 这是插件的id,必须唯一,最好使用公司包名,采用com.xxx.xxx的形式-->
  <id>com.xiaojin.li.hello.plugin.demo</id>
  <!-- 插件的名称,会显示在插件管理页面 -->
  <name>这是我的第一个plugin</name>
  <!-- 插件的版本 -->
  <version>1.0</version>
  <!--  -->
  <vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>

  <!-- 插件的描述 -->
  <description><![CDATA[
      Enter short description for your plugin here.<br>
      <em>most HTML tags may be used</em>
    ]]></description>

  <!-- 插件的更新说明 -->
  <change-notes><![CDATA[
      Add change notes here.<br>
      <em>most HTML tags may be used</em>
    ]]>
  </change-notes>

  <!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
  <idea-version since-build="173.0"/>

  <!-- 插件项目依赖的第三方库 -->
  <depends>com.intellij.modules.platform</depends>
  <depends>com.intellij.modules.lang</depends>
  <depends>com.intellij.modules.java</depends>

  <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
  </extensions>

  <!-- 插件的菜单项 -->
  <actions>
    <!-- id为菜单的id,class为该菜单对应的类,text为该插件菜单对应的显示的文本,-->
    <action id="files.PluginDemoActionABC" class="files.PluginDemoActionABC" text="PluginDemoActionABC" description="files.PluginDemoActionABC">
      <!-- 将该插件添加到Tools菜单内,并且排在第一个 -->
      <add-to-group group-id="ToolsMenu" anchor="first"/>
    </action>
  </actions>
</idea-plugin>
  • 新建菜单项,推荐使用Plugin Devkit创建一个Action,这样就不用自己在plugin.xml中添加Action。

image.png

  • 新建一个FileTemplate文件备用
#if (${PACKAGE_NAME} != "")
package ${PACKAGE_NAME}
#end
#if (${INTERFACES} != "")
import java.io.Serializable;
#end

public class ${NAME} ${INTERFACES}{
#if (${INTERFACES} != "")
private static final long serialVersionUID = 1L;
#end
}
  • 编写Action文件
package files;

import com.intellij.ide.IdeView;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import org.apache.commons.collections.map.HashedMap;
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;

import javax.swing.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 插件生成类demo
 */
public class PluginDemoActionABC extends AnAction {

    private String pasteStr = "name String\n" +
            "age int\n" + "id int\n";

    /**
     * 点击时会执行该方法
     * @param e
     */
    @Override
    public void actionPerformed(AnActionEvent e) {
        generateFile(e,"NameClass"+System.currentTimeMillis(),pasteStr);
    }

    /**
     * 生成文件
     */
    private void generateFile(AnActionEvent anActionEvent,String fileName,String pasteStr){
        //得到当前工程对象
        Project project = anActionEvent.getProject();
        //得到目录服务
        JavaDirectoryService directoryService = JavaDirectoryService.getInstance();
        //得到当前路径 - 得到相对路径
        IdeView ideView = anActionEvent.getRequiredData(LangDataKeys.IDE_VIEW);
        PsiDirectory psiDirectory = ideView.getOrChooseDirectory();

        //填入模板文件中的参数
        Map<String,String> map = new HashMap();
        map.put("NAME",fileName);
        map.put("INTERFACES","implements Serializable");
        map.put("PACKAGE_ NAME","");

        //生成文件
        PsiClass psiClass = directoryService.createClass(psiDirectory,fileName,"GeneFile",false,map);
        //开始加入字段
        WriteCommandAction.runWriteCommandAction(project, new Runnable() {
            @Override
            public void run() {
                geneModelFields(pasteStr,project,psiClass);
            }
        });
    }

    /**
     * 生成类中的属性
     * @param pasteStr
     * @param project
     * @param psiClass
     */
    private void geneModelFields(String pasteStr,Project project,PsiClass psiClass){
        if(pasteStr == null){
            return;
        }
        PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
        ///根据字符串生成代码
        String[] lineString = pasteStr.split("\n");
        StringBuilder stringBuilder = new StringBuilder();
        for(String s : lineString){
            String[] temp = s.split(" ");
            String fieldName = temp[0];
            String fieldType = temp[1];
            stringBuilder.append("public" + " " + fieldType + " " + fieldName + ";");
            PsiField psiField = factory.createFieldFromText(stringBuilder.toString(),psiClass);
            psiClass.add(psiField);
            stringBuilder.delete(0,stringBuilder.length());
        }
    }
}
  • 关于调试,选择run后,会自动启动另一个窗口,可以在该窗口的Tools菜单中看到我们刚才创建的菜单,点击并创建类。

image.png

  • 如果要生成一个插件,安装到Android Studio中,在Run中选择Prepare Plugin Module 'plugindemo001' For Deployment即可导出插件,可以Android Stuido的插件管理中选择Install Plugin from Disk。

image.png

image.png