美文网首页
Android Template 开发

Android Template 开发

作者: 苏坡坡要吃婆婆酥 | 来源:发表于2020-07-22 11:32 被阅读0次

1.模板能干什么?

便捷开发,懒人福音,一键生成代码。若有疑问,自行百度。
Studio中自带的模板可以体验一下。


image-20200713104328387.png

2.模板位置

模板位于AndroidStudio安装目录下的...\plugins\android\lib\templates文件夹下。

image-20200713104647811.png

如果需要生成Activity类型模板就在activities文件夹。

如果需要生成Fragment类型或者其他Java类模板就放在other文件夹。

3.模板构成

我们可以参考activities文件夹中的EmptyActivity模板。

image-20200713105200723.png

模板构造就是如图这五个部分,不信你也可以打开其它模板文件看看,构造都是酱紫。

1.root文件夹

这个里面就是放的就是我们需要模板化的代码。

正常情况下activity的模板root文件夹里面应该是。

image-20200713122755893.png

包括这三个部分。res里面放对应资源文件layout什么的。src则为模板代码类。

image-20200713105618004.png

打开可以看到有两个同名的页面文件一个是java语法一个是kt语法。我们打开see see。

package ${packageName};

import ${superClassFqcn};
import android.os.Bundle;
<#if (includeCppSupport!false) && generateLayout>
import android.widget.TextView;
</#if>

public class ${activityClass} extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
<#if generateLayout>
        setContentView(R.layout.${layoutName});
       <#include "../../../../common/jni_code_usage.java.ftl">
<#elseif includeCppSupport!false>

        // Example of a call to a native method
        android.util.Log.d("${activityClass}", stringFromJNI());
</#if>
    }
<#include "../../../../common/jni_code_snippet.java.ftl">
}

看到一些其奇怪鱼头符号 <#incloude ...>,还有什么JNI啊,感觉好怕怕,好高大上,不要慌,这些对我们目前来说都毫无卵用,自行屏蔽。

<#if><#else if></#if> ,盲猜这是个if判断语句,然后你去百度一下发现,对的没错,他就是 ftl 的判断语法。

精减代码。

package ${packageName};

<#if (includeCppSupport!false) && generateLayout>
import android.widget.TextView;
</#if>

public class ${activityClass} extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
<#if generateLayout>
        setContentView(R.layout.${layoutName});
</#if>
    }
}

这下可以看到这跟我们平时写的代码没有多大区别。就是包名,类名,布局名都被${packageName}, ${activityClass}, ${layoutName}代替了。

2.template.xml.ftl

它就是生成模板时候的预览界面。

AS中在包上右键-New-Activity-Empty Activity就会打开创建当前模板。

image-20200713112907055.png
<?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" />//该模板所处的分类,可以自己写一个分类。跟templates文件夹下的activities文件夹无关。
    <formfactor value="Mobile" />//电子产品,有什么安卓TV啊,手机啊,手表啊,写不写无所谓。

//一个parameter代表上图中的一行菜单。
//id标识该parameter,可以用${id值}来引用该parameter的值,例如${activityClass};
//name是该parameter呈现到上图时的名称;
//type决定了该parameter的行为,如boolean为勾选框,string为文本输入框,pacakage为下拉框选择包;
//constraints为约束,例如class要按标准类名来命名(首字母大写),unique表明这个parameter的string必须唯一,noempty是非空;
//suggest是建议值,比如Activity Name中suggest为${layoutToActivity(layoutName)},则id为layoutName的parameter改变值时,会执行${layoutToActivity(layoutName)}该函数,返回的值就是Activity Name显示的值。注意是实时改变;
//default是parameter显示的默认值;
//help是选中该parameter时的提示string。

    <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.xml.ftl和recipe.xml.ftl文件
    <globals file="globals.xml.ftl" />
    <execute file="recipe.xml.ftl" />

</template>

看完之后是不是发现预览界面挺简单的,就跟我们写页面的xml一样。

3.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>

从名字就可以盲猜出来,它主要是声明一些全局变量。<#include>导入部分必须导入,剩下那些自己看着定义。用于页面或者布局文件中判断。

4.recipe.xml.ftl

主要用于将root下的源代码ftl文件和资源文件整合到项目中,涉及一些freemarker语法,写上注释解释一下。

<?xml version="1.0"?>
<recipe>
    //include语法,跟C中的include是一个意思,就是引用这个文件
    <#include "../common/recipe_manifest.xml.ftl" />

//if语法,这里代表了假如id为generateLayout的值为true,则往if里面走
<#if generateLayout>
    <#include "../common/recipe_simple.xml.ftl" />
    //open语法,这里指打开${escapeXmlAttribute(resOut)}/layout/目录下的${layoutName}.xml文件,其中${escapeXmlAttribute(resOut)}/输出的目录就是项目中的res目录
    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</#if>
    //instantiae语法,这里是将root/src/app_package/目录下的SimpleActivity.java.ftl解析成项目中${escapeXmlAttribute(srcOut)}/${activityClass}.java,其中${escapeXmlAttribute(srcOut)}/输出的目录就是项目中的src目录
    <instantiate from="root/src/app_package/SimpleActivity.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />

    <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
</recipe>

正常操作下,我们在此导入的xml文件也应该和activity在一个目录,当前演示并非在同一地方。

    <instantiate from="root/res/layout/recipe_simple.xml.ftl"              to="${escapeXmlAttribute(resOut)}/layout/${escapeXmlAttribute(layoutName)}.xml" />

    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

正常操作下,在此我们还应引入清单文件。

    <merge from="root/AndroidManifest.xml.ftl"             
            to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />

正常操作代码。

<?xml version="1.0"?>
<recipe>
    //将新建页面在AndroidManifest注册
    <merge from="root/AndroidManifest.xml.ftl"             
            to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
    
//if语法,这里代表了假如id为generateLayout的值为true,则往if里面走
<#if generateLayout>

    <instantiate from="root/res/layout/recipe_simple.xml.ftl"                   to="${escapeXmlAttribute(resOut)}/layout/${escapeXmlAttribute(layoutName)}.xml" />
    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
    
</#if>

//instantiae语法,这里是将root/src/app_package/目录下的SimpleActivity.java.ftl解析成项目中${escapeXmlAttribute(srcOut)}/${activityClass}.java,其中${escapeXmlAttribute(srcOut)}/输出的目录就是项目中的src目录

//open语法,这里指打开${escapeXmlAttribute(resOut)}/layout/目录下的${layoutName}.xml文件,其中${escapeXmlAttribute(resOut)}/输出的目录就是项目中的res目录

    <instantiate from="root/src/app_package/SimpleActivity.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
    <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
</recipe>

root文件夹中的AndroidMainfest内容如下。

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application>
        <activity android:name="${packageName}.activity.${activityClass}"
                  android:screenOrientation="portrait"/>
    </application>

</manifest>
5.png

创建模板时候的预览图。

相关文章

网友评论

      本文标题:Android Template 开发

      本文链接:https://www.haomeiwen.com/subject/qfezkktx.html