1、android 代码模板介绍
开发中经常需要写大量的代码,如果能把写代码的效率提升,一键自动生成代码将是一件非常愉快的事情。让我们来领略andoid studio的FreeMarker给我们带来的这一份愉悦吧~
1.1、什么是android code template
- 简单来说是可以通过一些简单的参数来生成包含代码和资源模板的机制。
- 可以通过eclipse的adt插件集成,并可以编辑模板文件
- android的模板是用freemarker写的,freemarker是一个java的模板引擎
- freemarker非常轻量级,相对于eclipse的EMF会轻量很多。更多关于EMF的介绍参考这里
1.2、模板生成流程
流程介绍:
简单来说android提供了一个界面可以让用户输入变量,并根据android studio目录下面的模板工程的ftl文件通过FreeMarker自动生成了相应的android 工程。以下对流程中的角色介绍:
- UI Parameters: 在android studio里面选择一个模板时会弹出一个参数列表的弹窗,这个弹窗里面填的参数会被填充到相应的模板代码中被执行。
- recipe.xml.ftl: 该文件的职责是控制如何生成模板文件列表。freemarker里面freemarker语法的文件(例如: ${xxxxx} 这种格式)都需要命名为.ftl后缀。
- MyActivity.java.ftl:为具体的模板文件,里面定义了该文件会根据传入的参数如何动态改变。这里可以是很多的模板文件,资源或文件夹。这些资源如何生成需要在recipe.xml.ftl里面控制。
这些文件最终通过freemarker在recipe.xml.ftl的控制下生成MyActivity.java
1.3、android 默认的模板
在android studio里面右键任意一个module点击”New”可以看到很多预置的默认模板,如下面图所示。这些模板具体的位置是在你android studio的安装目录下,具体路径为“plugins\android\lib\templates”
选择具体的模板后会弹出参数对话框,里面可以按格式填写一些参数。填写完成后点击finish就会生成一个android 工程,非常方便,大大的提升了程序猿哥哥的开发效率。
2、如何调试开发和模板文件
看完上面介绍,你应该对android 的模板比较了解了,freemarker的目的是为了提升编码效率,把你生命中宝贵的时间放在思考和创新上,而不是重复的无意义的拷贝和修改文件上。有了android studio预置的模板你可以快速生成一个activity,等等。网络上面也有很多很优秀的模板资源,你可以拷贝到android studio的模板目录下面,重启android studio你就可以看到新添加的模板了。
除此之外做为一个有追求的程序员,你可能期望能自己编写模板文件,调试并制作自己的模板。接下来会讲解如何编写和调试自定义的模板。
2.1、android studio模板文件结构
以android的自带的LoginActivity模板为例介绍一下模板工程目录结构
- root:存放模板源文件,包括模板代码,资源等
- globals.xml.ftl: 包含全局的常量定义(global values),记住globals.xml里面定义的常量不能相互引用,如果需要相互引用,可以通过assign标签实现。参考下面的使用例子:
12<#assign localParam1=templateParam1+'/test'><global id="globalParam1" value="${localParam1}/main" /> - recipe.xml.ftl 上面已经介绍,这个是模板执行文件,该文件的职责是控制如何生成模板文件列表。该模板文件需要用到修改文件所有的基本操作包括:copy(文件复制),instantiate(文件修根据模板表达式的修改操作),merge(文件合并)。下面的图简单表达了recipe.xml如何让模板文件生成对应输入文件的原理,理解起来很简单我们经常copy类似的工程来修改时,经常做的操作也是:复制,修改和内容合并(例如:beyondcompare工具,在拷贝其它人代码时经常用到)
对应的xml结构如下,这个结构对应到上面的原理图,用html标签的方式表达出来,这种标签的表达方式非常容易理解,因为和android的res的xml风格是一致的。
- template_login_activity.png 该文件是展示在android studio选择模板对话框上面的图片,文件名需要和template.xml里面定义的thumbs标签下面的一致
- template.xml 模板文件,这个文件是android studio模板的入口文件,会包含模板工程中主要的几个配置文件入口,包括:自定义变量(metadata),常量(globals.xml.ftl),以及recipe(模板执行文件)。
对应的xml结构如下,可以看得出来模板是按照标签定义的顺序执行的,最后一个标签为<execute>,这个就是模板的执行入口了,看到这里你会不会角色android studio的FreeMarker没有想象中的那么神秘了
整个的数据流程如下,template.xml里面的recipe.xml.ftl会根据定义的parameter, global-values去执行FreeMarker表达式生成目标文件:
2.2、android studio模板编辑工具
freemarker官网上面介绍了很多编辑工具和插件,详细可以转移到这里
我常用的是eclipse插件,以下是对各种eclipse版本如何集成freemarker插件的介绍:
我的eclipse版本是Oxygen.1a (4.7.1a)
- 在Help>Install New Software… 里面选择相应的下载链接,例如我的是Oxygen这个链接,选择后再搜索一栏输入market就可以找到”Marketplace Client”,点击安装即可
2. 在Help>”Eclipse Marketplace…”搜索“JBoss Tools”并安装“JBoss Central Community”;“FreeMarker IDE”
3. 此时可以打开本地android studio安装目录下面的模板工程进行编辑了。一个”LoginActivity”模板打开的例子如下:
3、freemarker常用的语法介绍
这里先介绍一下freemarker,freemarker是apache旗下的一款模板引擎,它是一个java 库基于模板和数据去输出txt格式文件(例如html网页,email, 配置文件,源码等等)。模板文件是使用Freemarker Template Language(FTL)语言编写,这是一个很简单,且专门对模板的语言,意味着你需要准备好数据然后可以用其它的编程语言来展示,例如你使用数据库查询语言实现了很复杂的查询,而模板仅仅对你准备好的数据进行展示,也就是说在模板里面你只需要专注于如何展示数据,在模板之外你需要专注于什么样的数据需要被展示。
上面这张图解释了模板和数据的关系,模板只关心如何把Data填充到相应的位置,模板其它的部分对于Freemarker而言就是文本。接下来我们可以了解下Freemarker的模板语言FTL,也许你会觉得非常简单,甚至一眼就能看懂,并快速将其运用到你自己的实践中。
3.1、 template.xml
android studio模板特有的xml格式的配置文件,用于定义一个android 模板。下面介绍一下这个模板的一些属性:
<template>
template.xml的根节点.
- format
该模板遵循的模板根式版本,应该为 3.
- revision
非必填。 此模板的版本(您可以在更新模板时增加),为整数。
- name
模板显示名称
- description
模板的描述
- minApi
非必填. 该模板允许的最小sdk level. IDE 会在执行模板时确保目标工程的minsdkversion不低于此值。
- minBuildApi
非必填. 此模板所需的最低Build api(以API级别表示)。 在实例化模板之前,IDE将确保目标项目的API级别大于或等于此值。 这确保模板可以安全地使用较新的API(可选地通过运行时API级别检查来保护),而不会在目标项目中编译时引起错误。
<dependency>
指明此模板需要目标工程提供相应的库,如果没有,那么IDE需要添加这些依赖
- name
需要依赖的library名称. 目前允许的值包括:
- android-support-v4
- android-support-v13
- revision
模板支持的最小的library 版本revision
<category>
模板类别,这个标签是非必要的
- value
模板的类型. 值应该为下面中的一个:
- Application
- Activity
- UI Components
<parameter>
用于定义用户自定义模板变量
- id
变量id, 可以在FreeMarker文件中被引用。例如这里的id定义为foo, 那么在FreeMarker文件中可以这样引用${foo}
- name
变量显示在模板对话框的名称.
- type
变量类型,可以为:string, boolean, enum, or separator.
- constraints
非必填,对变量值得约束限制(constraint),定义多个Constraints,可以用 ‘|’ 符号来分隔,类似于android的风格。可以使用的constraint 类型有:
- nonempty — 值不能为空
- apilevel — 这个值是一个数字的API level
- package — 必须是一个合法的java包名格式
- class — 必须是一个合法的java class名称
- activity — 必须是一个完全合法的 activity class名称
- layout — 必须是一个布局资源名称
- drawable — 必须是一个drawable 资源名称
- string — 必须是一个合法的string 资源名称
- id — 必须是一个合法的id 资源名称
- unique — 这个值是唯一的,这个constraint只有在同时有其它constraint存在的情况下才起作用。例如layout, 就意味着这个值不应该和一个已经存在的布局资源名称重名。
- exists — 这个值必须已经存在; 这个constraint只有在同时有其它constraint存在的情况下才起作用,例如layout, 意味着这个值代表一个已经存在的layout布局资源名称。
- suggest
非必填. 需要填写一个FreeMarker表达式用于自动推荐一个默认值 (换句话说是 ‘动态的 default’). 当用户修改了其它的变量值,且suggest当前的值没有改为非默认值(非default值),那么suggest的值将会根据表达式改变。这个看起来会有点混乱,因为suggest的值可以跟着表达式随着其它的变量的值变化而变化, 所以 这个方法可以让用户在编辑变量值得同时,自动让其它的变量更新为合理的默认值。
- default
非必填. 这个变量的默认值.
- help
当用户选择这个变量时android studio上面提示给用户的帮助信息.
<option>
当变量类型为 enum时, 代表值的可选项.
- id
当选择该option时变量被设置的值。
- minApi
非必填. 当选择该option时需要的的最小API level . IDE 需要在执行模板任务之前确保目标工程的minSdkVersion 不低于此值。
- [text]
option标签中的内容会显示在界面的下拉选项上面.
<thumb>
模板的缩略图. <thumb> 标签应该包含在<thumbs>标签里面. 标签中的内容应该是缩略图片文件的路径. 如果有多个<thumb>, 这些thumb会被认为是选择器(selectors)值. 例如, <thumbs>里面包含两个<thumb>
1 2 3 4 |
<thumbs> <thumb>template.png</thumb> <thumb navType="tabs">template_tabs.png</thumb> </thumbs> |
模板的缩略图将会在<parameter>中定义的navType变量值为tabs时显示template_tabs.png,如果navType是其它值将会显示 template.png 缩略图
3.2、Freemarker的语法标记介绍
- 插值,用于在模板中插入一个数据
1 |
${data} |
2. FTL语言中的if else标签,通过动态的数据(这里是isDebug)让模板最终生成不同的文本内容
1 2 3 |
<#if isDebug == "true"> <#else> </#if> |
3. FTL中的注解
1 |
<#-- 注释内容 --> |
4. 模板方法– String slashedPackageName(String)
这个方法是把对应的包名转换为相应的路径字符串,例如:com.example.conio 转换为 com/example/conio 目录字符串
1 |
<global id="srcOut" value="src/${slashedPackageName(package)}"/> |
5. 模板方法– String underscoreToCamelCase(String)
这个方法是将由下划线分隔的字符串转换为相应的驼峰格式的字符串,例如test_conio,会转换为TestConio
6. 字符串转大写和小写
把指定字符串转成大写
1 |
${data?upper_case} |
把指定字符串转成小写
1 |
${data?lower_case} |
更多模板方法参考:https://freemarker.apache.org/docs/ref_builtins_string.html
更多的Freemarker语法参考官网的《FreeMarker Manual》
3.2.1 Freemarker中常用的转义
在生成gradle文件的模板时,我们会遇到这种情况:gradle里面也是用${xxx}表示这是一个变量,此时freemarker解析时也会解析这个标签,所以会出错,此时我们需要对gradle文件中的${}做转义,可以使用如下:
1 |
${r'${obj.name}'} |
这样最终显示的结果就是:${obj.name},而不会被freemarker解析。这里要注意,前边那个“r”字符是关键点
4、模板文件自动拷贝脚本
Android Studio安装模板并生效需要关注两件事情:
- 拷贝模板到Android Studio安装目录下面的模板列表目录下面
- 重启Android Studio工具
对于拷贝操作,我们可以用脚本来实现。windows环境下bat脚本代码入下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
@echo off & chcp 936 rem 添加自己的android studio路径到下面数组中,并修改for循环里面的数组大小 setlocal enabledelayedexpansion set AndroidStudioPathArr[0]=C:\Program Files\Android\Android Studio set AndroidStudioPathArr[1]=D:\Program Files\Android\Android Studio for /l %%n in (0,1,2) do ( echo !AndroidStudioPathArr[%%n]! set item=!AndroidStudioPathArr[%%n]! if exist !item! ( echo 找到Android Studio安装目录,开始模板升级:!item! set channelTemplatePath=!item!\plugins\android\lib\templates\activities\NewGoChannel if exist !channelTemplatePath! ( echo 模板已经存在,先删旧模板:!channelTemplatePath! del /S /Q "!channelTemplatePath!" rmdir /S /Q "!channelTemplatePath!" echo 删旧模板成功:!channelTemplatePath! ) else ( echo 无此模板路径:!channelTemplatePath! ) echo 创建新的模板目录:!channelTemplatePath! mkdir "!channelTemplatePath!" echo 复制当前模板到Android Studio目录:!channelTemplatePath! robocopy .\source "!channelTemplatePath!" /mir echo 更新模板完成,请重启Android Studio完成升级操作! ) else ( echo 本地无此Android Studio安装目录,跳过:!item! ) ) |
Great beat ! I would like to apprentice at the same time as you amend
your website, how could i subscribe for a blog website?
The account aided me a appropriate deal. I have been tiny bit acquainted of this your broadcast
offered vibrant transparent concept