AndroidStudio 代码生成插件Code Generator

前言

前几天在做MVP迁移,把项目旧代码替换为使用MVP,给我的感觉就是重重复复的体力劳动。MVP项目平常的开发,要多建几个类,多十几个接口方法。像一些TextView的setText,及View的Visibility、Enable操作,写的特烦,然后发现一个特好用的代码生成插件,批量生成对应的方法。

安装

原Github地址
我的GitHub(入口放在倒数第一项,方便操作)

  1. 到Release页,下载Jar文件。
  2. AS中Plugins选择从磁盘安装。

使用

1.Alt + Insert 调出Generate窗口
2.选择CodeGenerate
3.选择需要生成的模板
4.选择针对的变量
5.点击ok生成


配置和自定义模板



类选择框

成员变量选择框
  • ui介绍
    左侧是生成项,右侧是对应的配置。
    右侧Template是代码生成模板,右侧Member是成员变量过滤。
    在右侧Template中,可以增加成员变量过滤的窗口,和类选择窗口。

  • 功能说明
    最完整的一次过程:
    1 .弹出类选择框,选择操作的类
    2.弹出变量框,显示在上面选中类里面过滤的变量
    3.选中需要所针对的变量,点击ok,批量生成对应变量的模板

  • 自定义
    模板使用的是velocity语言,可以简单了解一下。其实可以仿照给的原始模板ToString 、Getter and Setter修改,进行自己的自定义。
    下面是作者提供的常用参数,在自定义模板中会用到

 Tutorial for writing your templates

 1. First you need to know basic syntax of velocity[1].
 2. Then it is necessary to understand the variable that CodeGenerator provides
    and its inner structure for retrieving the information you need for generating code.
 3. Learn to use the utils provided so that you can ask for further information
    or reduce your workload.

 Variables Provided (Class Mode)
 -------------------------------
 Class mode means you want to create new classes(file).

 - ClassName: String     The name spcified by `Target Class Name`
 - PackageName: String   The package name specified by `Target Class Name`
 - class0: ClassEntry    The class that the action is triggered upon
   - raw: PsiClass
   - String packageName
   - importList: List<String>
   - fields: List<FieldEntry>
   - allFields: List<FieldEntry>
   - methods: List<MethodEntry>
   - allMethods: List<MethodEntry>
   - innerClasses: List<ClassEntry>
   - allInnerClasses: List<ClassEntry>
   - typeParamList:  List<String>
   - name: String
   - superName: String
   - superQualifiedName: String
   - qualifiedName: String
   - typeParams: int
   - hasSuper: boolean
   - deprecated: boolean
   - enum: boolean
   - exception: boolean
   - abstract: boolean
   - implementNames: String[]
   - isImplements(String): bool
   - isExtends(String): bool
   - matchName(String): bool

 - class1: ClassEntry    The first selected class, where `1` is the postfix
                         you specify in pipeline
   ...

 - MemberEntry (FieldEntry/MethodEntry common properties)
    - raw: PsiField(for field), PsiMethod(for method)
    - name: String
    - accessor: String
    - array: boolean
    - nestedArray: boolean
    - collection: boolean
    - map: boolean
    - primitive: boolean
    - string: boolean
    - primitiveArray: boolean
    - objectArray: boolean
    - numeric: boolean
    - object: boolean
    - date: boolean
    - set: boolean
    - list: boolean
    - stringArray: boolean
    - calendar: boolean
    - typeName: String
    - typeQualifiedName: String     //包含路径
    - type: String
    - boolean: boolean
    - long: boolean
    - float: boolean
    - double: boolean
    - void: boolean
    - notNull: boolean
    - char: boolean
    - byte: boolean
    - short: boolean
    - modifierStatic: boolean
    - modifierPublic: boolean
    - modifierProtected: boolean
    - modifierPackageLocal: boolean
    - modifierPrivate: boolean
    - modifierFinal: boolean

 - FieldEntry
   - constant: boolean
   - modifierTransient: boolean
   - modifierVolatile: boolean
   - enum: boolean
   - matchName(String): bool

 - MethodEntry
   - methodName: String
   - fieldName: String
   - modifierAbstract: boolean
   - modifierSynchronzied: boolean
   - modifierSynchronized: boolean
   - returnTypeVoid: boolean
   - getter: boolean
   - deprecated: boolean
   - matchName(String): bool

 Variables for Body Mode
 -----------------------
 - class0: ClassEntry         The current class
 - fields: List<FieldEntry>   All selected fields
 - methods: List<MethodEntry> All selected methods
 - members: List<MemberEntry> selected fields+methods
 - parentMethod: MethodEntry  The nearest method that surround the current cursor

 Utilities
 ---------
 - settings: CodeStyleSettings settings of code style
 - project: Project            The project instance, normally used by Psi related utilities
 - helper: GenerationHelper
 - StringUtil: Class
 - NameUtil: Class
 - PsiShortNamesCache: Class   utility to search classes
 - PsiJavaPsiFacade: Class     Java specific utility to search classes
 - GlobalSearchScope: Class    class to create search scopes, used by above utilities
 - EntryFactory: Class         EntryFactory.of(...) to turn PsiXXX to XXXEntry.

 Other feature
 -------------
 - Auto import.      If the generated code contains full qualified name, Code Generator will try to
                     import the packages automatically and shorten the name.
                     For example `java.util.List<>` -> `List<>`

 References
 ----------
 - Velocity syntax: http://velocity.apache.org/engine/1.7/user-guide.html

另外一个比较需要的方法,就是查找集成指定的类的 成员变量,比如我要给找出所有继承了View的成员变量,然后统一生成setVisibilityXXX()方法方法。因为在MVP时候,经常用到这个,还有TextView的setTextXXX(),都是只有View和TextView才拥有的方法。下面这个是在Member选项卡中的代码,作用是过滤所有继承android.view.View这个类的成员变量。

 Specified Class Type Filter
 -------------
 #set($typeTarget = "android.view.View")

 #set($availableMembers = $class0.members)
 #set($javaPsiFacade = $JavaPsiFacade.getInstance($project))
 #set($global = $GlobalSearchScope.allScope($project))
 #set($xtype = $javaPsiFacade.findClass($typeTarget, $global))

 #set($availableMembers = [])
 #set($methodNames = [])

 #foreach($member in $class0.members)
     #set($memberType = $member.type.split("&lt;").get(0))
     #set($type = $javaPsiFacade.findClass($memberType, $global))
     #if ($type.qualifiedName == $typeTarget || $type.isInheritor($xtype, true))
         $availableMembers.add($member)
     #end
 #end

我的模板

之前对项目进行MVP重构时候,很烦那些setText()、setEnabled()、setVisibility()之类的,所以找到了这个控件,然后简单下学了一下自定义,自己写了模板,需要的可以直接把文件拿下来导入使用。根目录下code-generator-my-setting.xml文件。
另外,因为原插件入口位置并不是在倒数第一项,强迫症的自己为了方便使用,把源码拿下来重新配置了一下,入口固定在倒数第一项,很方便,感兴趣,可以下项目中的jar(重新编译之后的插件)导入使用。
GitHub

总结

在生成代码方面,该插件的功能绝对是最强大的,最灵活,完全自定义,还可以选择指定类。只要配置了一次模板,就可以一劳永逸。
唯一的缺憾就是不支持文件生成,否则MVP模式的文件也无需手动创建了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,008评论 25 707
  • 文/冰焰free 陈小希喜欢江辰,所有人都知道。不论是她最好的闺蜜林静晓,还是喜欢着她的吴柏松,或者是经常和他们厮...
    冰焰free阅读 688评论 0 1
  • 自从妈妈从2017年6月份确诊为肠癌,做完手术后医生说:“出于安全考虑,需要化疗”预防…… 术后休息了半个月左右就...
    蠢萌猫咪阅读 467评论 0 0
  • 这个周末就是母亲节了,今天放学去接娃,一见到我就急着把他做的手工花送给我 ,说祝我节日快乐!呵呵,好像是第一次收...
    云沐妈妈阅读 215评论 0 0
  • [HTML && CSS] 1.Doctype严格模式与混杂模式-如何触发这两种模式,区分它们有何意义? 严格模式...
    装在壳子里的刺猬阅读 342评论 0 1