本文详细介绍模板相关的知识和如何制作Android模版及使用,便于较少不必要的重复性工作。比如我在工作中如果要创建一个新的模块,就不要需要创建MVP相关的几个类:Model、View、Presenter、Entity等。
本文专门介绍和模板
相关的知识,那么问题来了:
- 模板是什么
- 模板使用位置
- 模板如何创建(包含模板存放位置)
- 模板如何使用
接下来,我就按照以上顺序为大家解读看起来高大上的模板
。
警告
本文所有模板路径均为Mac下的路径,Windows用户也可以查看路径中的相关信息,进而快速定位。
模板是什么
个人理解:模板即为了帮助人们简化某些固定而繁琐的操作而制作的工具,用于快速实现这些固定而繁琐的操作。
模板使用位置
当我们在使用AndroidStudio进行开发的时候,将鼠标选中工程项目,然后右击可以在New选项下面看到很多AndroidStudio提供给我们的模板类别,例如:Activity、AIDL等。具体可看下图:
细心的你会发现在这些模板的上面有一个选项:Edit File Templates...
,如下图所示:
点击这个选项,会进入自定义模板页面,其中内置的变量在页面下方都有解释,是不是很方便,但是它有一个致命的缺点:一次只能创建一个java文件。具体可看下图:
因为觉得这个很简单,所以我就不做过多阐述了,接下来我就仔细阐述一下,如何一次创建多个java文件,而且还可以选择是否包含xml文件。
模板如何创建(包含模板存放位置)
警告
如果直接复制相关代码的话,请注意其中的注释,可能会带来一些问题,如果出现问题,可以把#开头的注释去除,再尝试!!!
如果不懂上面这段话的意思的话,可以先行跳过。
FreeMarker
AndroidStudio的模板是使用模板引擎制作的,有兴趣的可以了解一下。
案例&解答
案例:
由于现在的项目使用的是类MVP架构
,所以基本上每个模块都需要entity、request、activity、presenter、viewmodel这五个类,无论是登录注册模块,还是商品详情页、首页、收益页面等模块,都无法摆脱这几个类,因此准备为这个类MVP架构
制作一个通用模板。
解答:
制作好模板之后,我想说,其实很简单,只是把会变化的部分用${...}
替换罢了,不过在这里我们还是老老实实的从头开始吧!
步骤
模板存放位置
首页我们进入AndroidStudio安装目录下的/plugins/android/lib/templates
文件夹,这就是AndroidStudio模板文件的目录了,到这里你可能还有所迷惑,因为你没有发现像我刚开始所说的Activity、AIDL等模板文件,没关系,你再进入activities
文件夹下面就可以看到Activity的相关模板了,进入other
文件夹就可以看到AIDL的相关模板了。
模板副本
这里我们选择activities
文件夹,然后你是不是觉得手足无措,不知道如何下手?其实一开始我也不知道怎么做,但是没关系,AndroidStudio不是已经提供给我们这么多模板了么,为了简单起见,我们在这里拷贝一份EmptyActivity
,并将其重命名为MVPActivity
,放在当前目录下。
目录结构
打开文件夹后,我们看到以下目录结构:
EmptyActivity |----globals.xml.ftl # 全局变量文件 |----recipe.xml.ftl # 配置要引用的模板路径以及生成文件的路径 |----root |----src |----app_package |----SimpleActivity.java.ftl # 模板文件 |----template_blank_activity.png # 创建模板时界面左边的预览图 |----template.xml # 模板的配置信息以及要输入的参数
接下我们可以根据目录结构顺序(建议按以下顺序看),打开看一下,这里大致介绍一下:
globals.xml.ftl
globals.xml.ftl
中都是类似
这样的语句,显然它的意思就是我定义了一个全局变量hasNoActionBar,它的类型是boolean,默认值为false。
recipe.xml.ftl
recipe.xml.ftl
稍微有些复杂,这里讲解以下instantiate、open等几个重要参数:
copy:复制--将from中的文件复制到to路径下,但并不会将ftl中得变量进行转换,即如果源文件中的类名为${activityClass},复制过后类名还是${activityClass}转换为我们需要的类名。
merge:合并--将from中的文件合并到to路径下的文件中。
instantiate:和copy类似,也是将from中的文件复制到to路径下,但是它会将${activityClass}转换为我们需要的类名。其实有这样一个过程:ftl->freemarker process -> java。
open:代码生成后,打开file中指定的文件。
SimpleActivity.java.ftl
打开SimpleActivity.java.ftl
文件,会发现和我们创建Activity类后及其类似,只是把包名、类名、布局名等用${...}
替换了,其实${...}
中得内容都是id名,这里不做过多阐述,我们继续往下看。
template.xml
template.xml
:打开以后你会发现这个文件好长,看来是重头戏了!!!是的,我们来详细解读一下:
一眼看去是不是和AndroidManifest.xml中得Application节点中的内容结构很相似(包括Application节点)
# 模板的描述信息# 模板类型,用于在菜单栏File-New下显示,如Activity、AIDL等 # 如同我们在创建module时所显示的类型,如:Wear、TV等。 # 创建模板时,选中文本框后,在底部显示的关于该文本框的帮助信息 template_blank_activity.png # 可选,用于创建模板时,在左边显示名为template_blank_activity的预览图片# 可选,将工程定义的全局变量包含进来 # 开始执行模板渲染
constraints值类型大全
Valid constraint types are: nonempty — the value must not be empty apilevel — the value should represent a numeric API level package — the value should represent a valid Java package name class — the value should represent a valid Java class name activity — the value should represent a fully-qualified activity class name layout — the value should represent a valid layout resource name drawable — the value should represent a valid drawable resource name string — the value should represent a valid string resource name id — the value should represent a valid id resource name unique — the value must be unique; this constraint only makes sense when other constraints are specified, such as layout, which would mean that the value should not represent an existing layout resource name exists — the value must already exist; this constraint only makes sense when other constraints are specified, such as layout, which would mean that the value should represent an existing layout resource name
template.xml制作
到这里相信大家对template.xml文件有了一定的了解了,好了,让我们来大干一场吧!
MVP版template.xml
既然这里详细的讲解了template.xml文件,我们先从template.xml文件入手吧,这里我就不一个个细说了,直接上完整代码:
# 需要修改# 可修改,此处已修改 # 一般不修改 # 可修改,此处未修改 # 一般不修改 # 一般不修改
template.xml文件的使用到这里就结束了,还是比较简单的,以下阐述之前所留下的两个问题:
(1)
suggest="${classToResource(activityClass)}_activity"
classToResource(activityClass):这句话的意思是,当我们在创建该模板后,在activityClass对应的文本框中输入某个值,比如:test,它会直接在layoutName对应的文本框中显示,即:test,所以以完整的语句(1)而言,此时layoutName对应的文本框中显示的应该是test_activity。
(2)
suggest="${underscoreToCamelCase(classToResource(activityClass))}ViewModel"
classToResource(activityClass)在(1)中描述的已经很清楚了,即为test,那么underscoreToCamelCase又是什么意思呢?其实就是将test转换为驼峰命名的方法,即Test。所以以完整的语句(2)而言,此时viewModelClass对应的文本框中显示的应该是TestViewModel。
如果你觉得文字描述过于繁琐,仍然看不懂的话,可以查看以下gif:
MVP版目录结构
接下来我们就可以把要制作成模板的类,拷贝到相应的文件夹中,此时的目录结构为:
MVPActivity |----globals.xml.filter |----recipe.xml.ftl |----activity_layout_recipe.xml.filter # 此文件与recipe类似,只是因为解耦思想,所以将class和layout分别引入 |----root |----src |----app_package |----classes |----Activity.java.ftl |----Entity.java.ftl |----Presenter.java.ftl |----Request.java.ftl |----ViewModel.java.ftl |----layout |----activity_layout.xml.ftl |----template.xml
Request.java.ftl
为了方便而又全面的进行讲解,此处我们以Request.java.ftl文件为例,这里我就直接上全部代码了:
package ${packageName}.request; # ${packageName}对应的是template.xml文件中id为packageName的参数设置的字符串,如果该类不在包名根目录下,可以在后面添加相应的module名。import android.support.annotation.NonNull; # 如果包名中未涉及到在创建模板时设置的包名和类名,则无需修改import ${packageName}.entities.${entityClass}; # 如果包名中涉及到在创建模板时设置的包名和类名,则只需相对应的进行修改即可/** * 将以下涉及到在创建模板时设置的包名和类名,进行如下相对应的替换即可,布局文件也是这样替换的!!! */public class ${requestClass} extends SHGetRequest<${entityClass}> { @Override protected Class<${entityClass}> getDataClass() { return ${entityClass}.class; } @Override protected TypeReference<${entityClass}> getDataTypeReference() { return null; } @NonNull @Override protected String getRequestUrl() { return null; }}
布局文件
接下来我们来看一下布局文件的替换:
虽然说tools命名空间一般都是可有可无的,这里为了全面,也讲述以下,你应该发现了一个从未见过的id:relativePackage,不用迷惑,估计你也想到了,其实我就是在globals.xml.ftl文件中定义了一个全局变量而已,它的值默认为包名,具体代码如下:
globals.xml.ftl
既然说到了globals.xml.ftl文件,我们就去看看好了:
<#include "../common/common_globals.xml.ftl" />
其实并没有什么,global代表的都是全局变量,#include代表的是引用的文件,相当于继承。
recipe.xml.ftl
然后就只有recipe.xml.ftl文件了,也快结束了:
<#include "../common/recipe_manifest.xml.ftl" /> # 引入同级目录中的activity_layout_recipe.xml.ftl文件,其内容会在下一节中讲述 <#include "activity_layout_recipe.xml.ftl" />
instantiate
的作用在上面已经讲的很清楚了,简单来说就是将ftl文件转换为java文件,而open
指的是在创建模板成功后,打开指定的文件,很简单吧,这里只有一个注意点:路径不要写错了!!!
${escapeXmlAttribute(srcOut)}代表的即为包名所代表的路径${escapeXmlAttribute(resOut)}代表的是res根目录
activity_layout_recipe.xml.ftl
之前因为解耦思想,所以把布局文件的recipe文件单独处理了,即为activity_layout_recipe.xml.ftl,打开文件,其实很简单:
这里就不做阐述了,大家看上一节就明白了。
模板如何使用
模板创建好之后,我们首先需要的是验证是否能够正确创建出我们需要的部分,且没有错误发生,这个过程其实就是模板使用的过程,具体可以参考。
总结
至此,Android模板制作已经全部完成了,本文篇幅还是比较长的,如果有什么疑问可以评论,我会尽力解决每一个问题的,谢谢!!!