每次创建新的Android Studio工程时,都需要手动修改一些工程的配置,
比如删除不必要的依赖、删掉Activity中不必要的代码 配置私有maven库的地址、增加公用的依赖库、修改.gitingore、关闭lint的严格检查、配置APK的输出路径等等,当有很多类似的项目的时候就有大量的无用功,
浪费时间,就可以考虑修改Android Studio默认的project和module模板。
默认模板路径
Android Studio的工程模板在安装目录的“\plugins\android\lib\templates\gradle-projects”文件夹下,这里面包含了导入工程模板、新建工程模板、新建module模板等。
![](/images/template path.png)
模板的文件结构
学习编写模板最好的方式就是参考Android Studio中已经提供的最简单的模板,那么在Android Studio中最简单的activity模板就是:Empty Activity了,我们打开该模板文件,首先对文件结构有个直观的了解,如图:
![](/images/empty activity.png)
文件夹包含
- template.xml
- globals.xml.ftl
- recipe.xml.ftl
- root文件夹 存放对应源码的ftl文件,以及资源文件
- 效果缩略图
下面我们逐一对上述每个文件的作用就行介绍。
template.xml
<?xml version="1.0"?>
<template
format="5"
revision="5"
name="Empty Activity"
minApi="9"
minBuildApi="14"
description="Creates a new empty activity">
<category value="Activity" />
<formfactor value="Mobile" />
<parameter
id="activityClass"
name="Activity Name"
type="string"
constraints="class|unique|nonempty"
suggest="${layoutToActivity(layoutName)}"
default="MainActivity"
help="The name of the activity class to create" />
<parameter
id="generateLayout"
name="Generate Layout File"
type="boolean"
default="true"
help="If true, a layout file will be generated" />
<parameter
id="layoutName"
name="Layout Name"
type="string"
constraints="layout|unique|nonempty"
suggest="${activityToLayout(activityClass)}"
default="activity_main"
visibility="generateLayout"
help="The name of the layout to create for the activity" />
<parameter
id="isLauncher"
name="Launcher Activity"
type="boolean"
default="false"
help="If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher" />
<parameter
id="backwardsCompatibility"
name="Backwards Compatibility (AppCompat)"
type="boolean"
default="true"
help="If false, this activity base class will be Activity instead of AppCompatActivity" />
<parameter
id="packageName"
name="Package name"
type="string"
constraints="package"
default="com.mycompany.myapp" />
<!-- 128x128 thumbnails relative to template.xml -->
<thumbs>
<!-- default thumbnail is required -->
<thumb>template_blank_activity.png</thumb>
</thumbs>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
其中
template中的name属性,对应新建Activity时显示的名字
category对应New的类别为Activity
剩下的,对应我们AndroidStudio新建Empty Activity的界面就非常好理解了,如图:
![](/images/empty thumbnail.png)
看到这个界面,大部分属性都应该能才出来了,我们重点看parameter,界面上每一个紫色框出来的部分都对应一个parameter,部分属性介绍:
- id :唯一标识,最终通过该属性的值,获取用户输入值(文本框内容,是否选中)
- name:界面上的类似label的提示语
- type : 输入值类型
- constraints:填写值的约束
- suggest:建议值,比如填写ActivityName的时候,会给出一个布局文件的建议值。
- default:默认值
- help:底部显示的提升语
这个部分对应界面还是非常好理解的,大家可以简单的修改一些字符串,或者添加一个parameter,重启AS,看看效果。
template.xml的最下面的部分引入了globals.xml.ftl和recipe.xml.ftl。
这两个我们会详细介绍。
globals.xml.ftl
<?xml version="1.0"?>
<globals>
<global id="hasNoActionBar" type="boolean" value="false" />
<global id="parentActivityClass" value="" />
<global id="simpleLayoutName" value="${layoutName}" />
<global id="excludeMenu" type="boolean" value="true" />
<global id="generateActivityTitle" type="boolean" value="false" />
<#include "../common/common_globals.xml.ftl" />
</globals>
通过名称可以猜到它是用于定义一些全局的变量,可以看到其内部有global标签,分别定义id,type,默认值。
同理,我们可以通过id的值访问到该值,例如:
${hasNoActionBar}的值为false。
recipe.xml.ftl
<?xml version="1.0"?>
<recipe>
<#include "../common/recipe_manifest.xml.ftl" />
<#if generateLayout>
<#include "../common/recipe_simple.xml.ftl" />
<open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</#if>
<instantiate from="root/src/app_package/SimpleActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
</recipe>
为了介绍,我将该xml中比较重要的几个标签都列出来了:
- copy :从root中copy文件到我们的目标目录,比如我们的模板Activity需要使用一些图标,那么可能就需要使用copy标签将这些图标拷贝到我们的项目对应文件夹。
- merge : 合并的意思,比如将我们使用到的strings.xml合并到我们的项目的stirngs.xml中
- instantiate : 和copy类似,但是可以看到上例试将ftl->java文件的,也就是说中间会通过一个步骤,将ftl中的变量都换成对应的值,那么完整的流程是ftl->freemarker process -> java。
- open:在代码生成后,打开指定的文件,比如我们新建一个Activity后,默认就会将该Activity打开。
在介绍instantiate时,涉及到了freemarker,不可避免的需要对它进行简单的介绍。
目前我们已经基本了解了一个模板其内部的文件结构了,以及每个文件大致包含的东西,我们简单做个总结:
- template 中parameter标签,主要用于提供参数
- global.xml.ftl 主要用于提供参数
- recipe.xml.ftl 主要用于生成我们实际需要的代码,资源文件等;例如,利用参数+MainActivity.java.ftl -> MainActivity.java;其实就是利用参数将ftl中的变量进行替换。
简单的freemarker语法
上面我们已经基本了解模板生成的大致的流程以及涉及到的文件,大致了解了我们生成的源码或者xml文件,需要经过:
ftl->freemarker process->java/xml
这样的流程,那么我们必须对freemarker有个简单的了解。
- 非常简单的例子
比如我们有个变量user=zhy;
有个ftl文件内容:helloL${user}
最后经过freemarker的输出结果即为 hello:zhy
- if语法
<#if generateLayout>
//生成layout文件
</#if>
看一眼就知道大概的意思了~有一定的编程经验,即使不知道这个叫freemarker,对于这些简单的语法还是能看懂的。
我们最后以Empty Activity模板的中的SimpleActivity为例:
root/src/app_package/SimpleActivity.java.ftl
package ${packageName};
import ${superClassFqcn};
import android.os.Bundle;
public class ${activityClass} extends ${superClass} {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
<#if generateLayout>
setContentView(R.layout.${layoutName});
</#if>
}
}
可以看到其内部包含很多变量,这些变量的值一般来源于用户输入和global.xml.ftl中预定义的值,经过recipe.xml.ftl中instantiate标签的处理,将变量换成实际的值,即可在我们的项目的指定位置,得到我们期望的Activity。
具体的模板实例
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!