因为暂时还没有考虑好顺序,先用A表示
自己也没有怎么接触过android studio的模版 只是参考 鸿洋 的博客,接触到了, 自己记录一下 具体参考: https://github.com/WanAndroid/AndroidStudioTemplates
(后面 http://robusttechhouse.com/tutorial-how-to-create-custom-android-code-templates/ 里面有说 用 freemarker ,最后生成java代码, freemarker记得之前的公司,Spring的页面有用到,感觉页面填充数据都差不多)
鸿洋博客指向的github地址 https://github.com/WanAndroid/AndroidStudioTemplates 参考的是
先参考
Paste_Image.png
Paste_Image.png
这里大体的意思是, 通过开始做的参数,去做 recipe的执行 执行是将【前面的参数】,【recipe模版】和【Activity模版】,通过FreeMarker生成对应的 java文件
在 AndroidStudioXXXPath\plugins\android\lib\templates\中, 有对应的代码 以Activity为例: 我们打开android studio后, 在 File -- New -- Activity 中,可以看见很多可以选的Activity, 会显示显示符合条件的Activity模版
Paste_Image.png
AndroidStudioXXXPath\plugins\android\lib\templates\activities 中,有
Paste_Image.png
我们可以对比,基本一样的(文件夹中,有几个没有显示而已)
我们以 EmptyActivity 为例: (因为自己猜测, 空的应该是最简单的)
Paste_Image.png
我们可以看见,对应的结构 大体为:
我们用大图看一下
Paste_Image.png
在把miniSdk, 新建 EmptyActivity , 可以看见对应的页面
Paste_Image.png
(对应的图片,和文件夹中的图片是一样的)
我们先看一下
<?xml version="1.0"?>
<template
format="5"
revision="5"
name="Empty Activity"
minApi="7"
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="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>
一半猜测,一半看文档吧 先自己猜测一下(感觉代码都是差不多的,很多时候好的结构,可以猜到大概) 这是一个标准的xml
最外面 template, 可以猜测到
其他的变量: category:类型,这里是 Activity thumbs:android,java,maven都会见过,对应的thumbnail,缩略图,这里指向当前文件夹的一个文件(我们可以发现,如果修改名字后,新建模版就不会显示图片了) globals:globals.xml.ftl,主观感觉,应该是一些全局的变量或者文件 execute:recipe.xml.ftl,主观感觉,应该是执行相关的
其他parameter们: parameter:自己感觉就是对应的变量,别的地方可以使用的 一共有的parameter(3个string类型, 2个boolean类型)
Paste_Image.png
对应一下,上图 发现全部可以对应上, 并且默认值,可以里面的默认值是一样的
<?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,应该都是 参数map,存放对应的id,type和value 最后有一个include android,或者html页面,都经常用到的关键字 我们找一下对应的位置: ../common/common_globals.xml.ftl ( 无论是linux,php,win,貌似都一样,/ 开头,表示绝对路径; 其他表示相对路径) 我们到父文件夹找到common文件夹 找到对应的文件
Paste_Image.png
common_globals.xml.ftl
<globals>
<#assign theme=getApplicationTheme()!{ "name": "AppTheme", "isAppCompat": true }>
<#assign themeName=theme.name!'AppTheme'>
<#assign themeNameNoActionBar=theme.nameNoActionBar!'AppTheme.NoActionBar'>
<#assign appCompat=theme.isAppCompat!false>
<#assign appCompatActivity=appCompat && (buildApi gte 22)>
<global id="themeName" type="string" value="${themeName}" />
<global id="implicitParentTheme" type="boolean" value="${(themeNameNoActionBar?starts_with(themeName+'.'))?string}" />
<global id="themeNameNoActionBar" type="string" value="${themeNameNoActionBar}" />
<global id="themeExistsNoActionBar" type="boolean" value="${(theme.existsNoActionBar!false)?string}" />
<global id="themeNameAppBarOverlay" type="string" value="${theme.nameAppBarOverlay!'AppTheme.AppBarOverlay'}" />
<global id="themeExistsAppBarOverlay" type="boolean" value="${(theme.existsAppBarOverlay!false)?string}" />
<global id="themeNamePopupOverlay" type="string" value="${theme.namePopupOverlay!'AppTheme.PopupOverlay'}" />
<global id="themeExistsPopupOverlay" type="boolean" value="${(theme.existsPopupOverlay!false)?string}" />
<global id="appCompat" type="boolean" value="${((isNewProject!false) || (theme.isAppCompat!false))?string}" />
<global id="appCompatActivity" type="boolean" value="${appCompatActivity?string}" />
<global id="hasAppBar" type="boolean" value="${appCompatActivity?string}" />
<global id="hasNoActionBar" type="boolean" value="${appCompatActivity?string}" />
<global id="manifestOut" value="${manifestDir}" />
<global id="buildVersion" value="${buildApi}" />
<#if !appCompat>
<global id="superClass" type="string" value="Activity"/>
<global id="superClassFqcn" type="string" value="android.app.Activity"/>
<global id="Support" value="" />
<global id="actionBarClassFqcn" type = "string" value="android.app.ActionBar" />
<#elseif appCompatActivity>
<global id="superClass" type="string" value="AppCompatActivity"/>
<global id="superClassFqcn" type="string" value="android.support.v7.app.AppCompatActivity"/>
<global id="Support" value="Support" />
<global id="actionBarClassFqcn" type = "string" value="android.support.v7.app.ActionBar" />
<#else>
<global id="superClass" type="string" value="ActionBarActivity"/>
<global id="superClassFqcn" type="string" value="android.support.v7.app.ActionBarActivity"/>
<global id="Support" value="Support" />
<global id="actionBarClassFqcn" type = "string" value="android.support.v7.app.ActionBar" />
</#if>
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
<global id="resOut" value="${resDir}" />
<global id="menuName" value="${classToResource(activityClass!'')}" />
<global id="simpleName" value="${activityToLayout(activityClass!'')}" />
<global id="relativePackage" value="<#if relativePackage?has_content>${relativePackage}<#else>${packageName}</#if>" />
</globals>
我们可以发现更多的global参数,存放的map值
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>
我们发现被 recipe 包裹,
<instantiate from="root/src/app_package/SimpleActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />就是
应该就是打开 root下面唯一的SimpleActivity.java.ftl 模版文件,复制到对应template.xml的parameter为activityClass的值的文件中
还是最上面的图
Paste_Image.png
Paste_Image.png
第一个图: 通过开始做的参数,去做 recipe的执行 也就是,在 template.xml 显示界面,并且获得对应参数的value,和globals.xml.ftl里面的value一起去做Recipe执行操作
第二个图: 执行是将【前面的参数】,【recipe模版】和【Activity模版】,通过FreeMarker生成对应的 java文件 这里图中 MyActivity.java.ftl 就是 上面例子中 SimpleActivity.java.ftl 文件