前言
前幾天在做MVP遷移眶根,把項(xiàng)目舊代碼替換為使用MVP豺谈,給我的感覺(jué)就是重重復(fù)復(fù)的體力勞動(dòng)。MVP項(xiàng)目平常的開發(fā),要多建幾個(gè)類倘屹,多十幾個(gè)接口方法韩容。像一些TextView的setText,及View的Visibility唐瀑、Enable操作,寫的特?zé)┎宓缓蟀l(fā)現(xiàn)一個(gè)特好用的代碼生成插件哄辣,批量生成對(duì)應(yīng)的方法。
安裝
原Github地址
我的GitHub(入口放在倒數(shù)第一項(xiàng)赠尾,方便操作)
- 到Release頁(yè)力穗,下載Jar文件。
- AS中Plugins選擇從磁盤安裝气嫁。
使用
1.Alt + Insert 調(diào)出Generate窗口
2.選擇CodeGenerate
3.選擇需要生成的模板
4.選擇針對(duì)的變量
5.點(diǎn)擊ok生成
配置和自定義模板
ui介紹
左側(cè)是生成項(xiàng)当窗,右側(cè)是對(duì)應(yīng)的配置。
右側(cè)Template是代碼生成模板寸宵,右側(cè)Member是成員變量過(guò)濾崖面。
在右側(cè)Template中,可以增加成員變量過(guò)濾的窗口梯影,和類選擇窗口巫员。功能說(shuō)明
最完整的一次過(guò)程:
1 .彈出類選擇框,選擇操作的類
2.彈出變量框甲棍,顯示在上面選中類里面過(guò)濾的變量
3.選中需要所針對(duì)的變量简识,點(diǎn)擊ok,批量生成對(duì)應(yīng)變量的模板自定義
模板使用的是velocity語(yǔ)言感猛,可以簡(jiǎn)單了解一下七扰。其實(shí)可以仿照給的原始模板ToString 、Getter and Setter
修改陪白,進(jìn)行自己的自定義颈走。
下面是作者提供的常用參數(shù),在自定義模板中會(huì)用到
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
另外一個(gè)比較需要的方法咱士,就是查找集成指定的類的 成員變量疫鹊,比如我要給找出所有繼承了View的成員變量,然后統(tǒng)一生成setVisibilityXXX()
方法方法司致。因?yàn)樵贛VP時(shí)候拆吆,經(jīng)常用到這個(gè),還有TextView的setTextXXX()
脂矫,都是只有View和TextView才擁有的方法枣耀。下面這個(gè)是在Member選項(xiàng)卡中的代碼,作用是過(guò)濾所有繼承android.view.View這個(gè)類的成員變量。
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("<").get(0))
#set($type = $javaPsiFacade.findClass($memberType, $global))
#if ($type.qualifiedName == $typeTarget || $type.isInheritor($xtype, true))
$availableMembers.add($member)
#end
#end
我的模板
之前對(duì)項(xiàng)目進(jìn)行MVP重構(gòu)時(shí)候捞奕,很煩那些setText()牺堰、setEnabled()、setVisibility()之類的颅围,所以找到了這個(gè)控件伟葫,然后簡(jiǎn)單下學(xué)了一下自定義,自己寫了模板院促,需要的可以直接把文件拿下來(lái)導(dǎo)入使用筏养。根目錄下code-generator-my-setting.xml文件。
另外常拓,因?yàn)樵寮肟谖恢貌⒉皇窃诘箶?shù)第一項(xiàng)渐溶,強(qiáng)迫癥的自己為了方便使用,把源碼拿下來(lái)重新配置了一下弄抬,入口固定在倒數(shù)第一項(xiàng)茎辐,很方便,感興趣掂恕,可以下項(xiàng)目中的jar(重新編譯之后的插件)導(dǎo)入使用拖陆。
GitHub
總結(jié)
在生成代碼方面,該插件的功能絕對(duì)是最強(qiáng)大的懊亡,最靈活慕蔚,完全自定義,還可以選擇指定類斋配。只要配置了一次模板孔飒,就可以一勞永逸。
唯一的缺憾就是不支持文件生成艰争,否則MVP模式的文件也無(wú)需手動(dòng)創(chuàng)建了坏瞄。