使用IntelliJ Platform Gradle Plugin2.x开发AndroidStudio代码模板插件

日常开发中我们通常都会使用一种架构,无论MVC、MVP、MVVM、MVI等都多多少少需要一些模板代码,之前我基于IntelliJ Platform Gradle Plugin 1.x开发过一个MVP的代码自动生成插件,2年多过去了,我已经忘记当如如何做的了,最近需要写一个MVI架构的模板代码生成插件,于是又重新学习了一遍。怕日后再忘记,于是这里就写篇博客记录一下吧,一是帮助日后的自己,二是帮助其他需要开发插件的同学。


一、 准备开发环境

  1. 要开发AndroidStudio插件需要使用的IntelliJ IDEA,所以先要下载并安装IntelliJ IDEA
    IntelliJ IDEA

注意:IntelliJ IDEA的版本最好与AndroidStudio的版本相对应。

  1. 然后为IntelliJ IDEA安装Plugin DevKit插件。
    Plugin DevKit

插件可以通过官网下载后通过桌面安装的方式安装也可以直接在Plugins -> Marketplace中搜索安装。

二、 创建IDE Plugin项目。

点击File -> New -> Project,然后在左侧找到IED Plugin选中;然后填写好相关字段后点击Create按钮进行创建项目;

创建IDE Plugin项目

Name: 为项目名称,自行命名即可。
Location:为项目保存到磁盘中的位置,选择你希望保存的位置即可。
Create Git repository:是否创建Git仓库,看个人需要。
Type: Plugin为插件,Theme为主题.。
Artifact:插件名称,默认为项目名称,也用于rootProject.name项目settings.gradle.kts文件中的 Gradle 属性值。一般不需要修改,保持默认就好。
JDK:选择与所需 Java 版本匹配的JDK。它将作为运行 Gradle 的默认 JRE,以及用于编译插件源代码的 JDK。
必须根据目标平台版本设置 Java 版本。

IDE版本 Java版本
2024.2+ Java21
2022.3+ Java17

三、修改项目配置

1. 获取wizard-template.jar并依赖进项目中。

从AndroidStudio的安装目录中找到plugins -> android -> lib -> wizard-template.jar,然后将wizard-template.jar复制一份放到我们自己插件项目跟目录中的lib文件夹中。因为后续我们要用到wizard-template.jar提供的Api开发模板代码生成插件。

2. 修改项目根目录的build.gradle.kts。

配置AndroidStudio目标版本以及依赖第一步中的wizard-template.jar

dependencies {
    intellijPlatform {
        create("AI", "2025.1.1.13")  //AI表示目标平台为AndroidStudio,2025.1.1.13表示目标AndroidStudio的版本。
        testFramework(org.jetbrains.intellij.platform.gradle.TestFrameworkType.Platform)

        bundledPlugin("org.jetbrains.android")  //添加android的依赖
        compileOnly(files("lib/wizard-template.jar"))  //依赖wizard-template.jar
    }
}

提示:有关配置字段的所有含义可参考官方文档。有关AndroidStudio的版本请查看AS发布版本列表

3. 修改plugin.xml。

打开src -> resources -> plugin.xml并进行修改。

提示: plugin.xml中的所有字段含义可参考官方文档

<depends>org.jetbrains.android</depends>
<depends>com.intellij.modules.androidstudio</depends>
<extensions defaultExtensionNs="com.android.tools.idea.wizard.template">
    <wizardTemplateProvider implementation="templates.PluginTemplatesProvider" />
</extensions>

templates.PluginTemplatesProvider为自己创建的模板提供者。代码如下:

class PluginTemplatesProvider : WizardTemplateProvider() {
    override fun getTemplates(): List<Template> {
        return listOf(
            template {
                name = "My Template"  //模板名称
                description = "This is a demo"  //模板描述
                category = Category.Activity  //模板分组,用于表示我们的模板希望出现在那个分组中。这里写的Activity表示等下会在Activity中看到这个模板。
                formFactor = FormFactor.Mobile
                screens = listOf(
                    WizardUiContext.ActivityGallery,
                    WizardUiContext.MenuEntry,
                    WizardUiContext.NewProject,
                    WizardUiContext.NewModule
                )

                //使用widgets为窗口添加组件,我们可以利用这些组件对我们的模板进行配置。
                val activityName = stringParameter {
                    name = "File Name" //字段名称
                    default = "MainActivity" //用于设置字段的默认值,本例设置为MainActivity,可根据自己需求来。
                    suggest = { //suggest为动态计算对调,可以根据其他字段的值的改变动态计算当前字段的值。
                        "MainActivity"  //这里返回动态计算后的值即可,本例假设计算的值为"MainActivity"。
                    }
                }
                widgets(
                    TextFieldWidget(
                        activityName
                    )
                )
                recipe = { templateData: TemplateData ->  //生成代码的回调,在这里可根据widgets窗口中填写的值进行代码的生成。
                    val template = templateData as ModuleTemplateData  //强转成可用的ModuleTemplateData类型

                    //声明要生成的模板代码的目标文件,这里我们使用用户输入的名字拼上.kt后缀,放到template.srcDir指定的目录中。
                    val targetFile = File(template.srcDir, "${activityName.value}.kt")

                    //recipe的高阶函数中会有一个RecipeExecutor类型的receiver,也就是this指向的是RecipeExecutor。
                    //也就是说this.save其实调用的就是RecipeExecutor.save()
                    this.save(
                        source = "Activity的伪代码,我们可以写任何我们想要的内容。",  //要生成的代码,这里我先随便写了,大家可以根据自身需求来。
                        to = targetFile //目标文件
                    )
                }
            }
        )
    }
}

四、 运行项目

点击IDE右上角的Run Plugin按钮则会下载并启动AndroidStudio。然后在希望创建模板代码的目录上点击鼠标右键,然后依次选择New -> Activity就可以看到我们刚刚创建的模板My Template了。

选择自己创建的模板

然后点击My Template就会出现我们为模板配置的弹窗。

模板配置弹窗

然后点击Finish按钮,就可以生成我们想要生成的代码。


生成的代码

至此,我们已经完成了开发工作,由于没人的需求不同,这里只是记录插件开发的流程,具体逻辑还需要根据我们自己的实际需求决定。

五、 Template 窗口组件介绍

在第四节中我们创建了一个PluginTemplatesProvider类,并重写了getTemplates函数,且返回了自己的TemplateTemplate是使用DSLtemplate函数构建的,而在其中我们使用到了widgets()这个方法,这是构建窗体的关键,第四节的栗子PluginTemplatesProvider中我仅仅使用了TextFieldWidget这一个组件,其实还有很多其他组件可供我们选择,下面我就来列举一下较为常用的(ParameterWidget):

TextFieldWidget 文本框组件。

TextFieldWidget组件需要传入一个StringParameter类型的参数,可使用stringParameterDSL构建。例如:

stringParameter {
    name = "File Name"
    default = "MainActivity"
}

EnumWidget<T : Enum<T>> 枚举下拉框组件。

EnumWidget<T : Enum<T>>组件是一个枚举选择组件,它接收一个EnumParameter<T>类型的参数,其表现形式是一个下拉框,可让我们选择不同的枚举值,我们可使用enumParameter<T>DSL构建EnumParameter<T>,例如:

enum class BasicType {
    Any, Boolean, String, Int, Long;
}

mParameter<BasicType> {
    name = "Select Type Of Response"
    help = "Choose type for data for response."
    default = BasicType.Any
    visible = { !respCreatorParameter.value }
}

PackageNameWidget 包名输入框组件。

PackageNameWidget是一个包名输入框,主要用于输入包名,它与TextFieldWidget的最大不同是对包名有一定的处理功能,可以通过下拉选择包。但它与TextFieldWidget一样,都是接收一个StringParameter类型的参数。

CheckBoxWidget 复选框组件。

CheckBoxWidget需要一个BooleanParameter类型的参数,主要用于让使用者做一些选择,BooleanParameter可以使用booleanParameterDSL构建,例如:

rameter {
    name = "Generate Parameter"
    default = false
    help = "Whether to create parameters for page requests for data."
}

六、 插件的打包及发布

定义版本号和组

一般在我们创建项目的时候在项目根目录的build.gradle.kts中就自动为我们生成的group&version的定义,一般如下:

plugins {
    id("java")
    id("org.jetbrains.kotlin.jvm") version "2.1.0"
    id("org.jetbrains.intellij.platform") version "2.5.0"
}

group = "io.stephen.mvi.templates"  //组件分组
version = "1.0-SNAPSHOT"  //组件版本


repositories {
    mavenCentral()
    intellijPlatform {
        defaultRepositories()
    }
}

我们在发布组件时可根据需要修改版本号(version)的值,也可以不修改。

设置组件ICON

创建项目后,会在resources目录下与plugin.xml同级有一个pluginIcon.svg文件,这个就是我们插件的Icon,我们可以根据需要更换这个Icon。

打包

  1. 打开Gradle任务列表。依次找到Tasks -> intellij platform -> buildPlugin。


    找到插件打包任务
  2. 双击buildPlugin任务,开始打包插件。在Run窗口中看到如下内容则表示打包成功。


    查看打包结果
  3. 打包好的ZIP格式的插件文件位于build/distributions目录中。

    打包好的插件

手动安装插件

1.将我们打包好的build/distributions目录中的插件拷贝出来,放到一个容易找到的磁盘目录中,然后打开我们开发用的AndroidStudio就可以手动安装了。
在AS中打开Settings,然后依次点击Plugins -> Setting -> Install Plugin from disk...,如下图所示:

手动安装插件

  1. 找到我们刚刚打包好的插件,然后点击安装就可以了。如下图所示及表示我们安装成功了。


    插件安装成功

发布插件到JetBrains Marketplace插件库

如果我们开发的插件希望被别人使用,也可以将插件发布到JetBrains Marketplace插件库,发布成功之后别人就可以在AndroidStudio的Plugins中搜索到我们的插件了。

不过发布需要的步骤稍微有点多,但是好在官方文档写的都比较详细了,大家可以查看官方文档,具体的发布流程这里就不在赘述了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容