避免重复造砖,快速构建简单重复的代码工作。
JSP
JavaWeb常用技术,通过在HTML页面技术里插入Java代码,动态生成Servlet代码。反过来解释,将页面表示逻辑从Java Servlet中抽离,结合HTML生成一个模板文件,通过编辑Jsp动态修改Controll层逻辑。Velocity
是基于MVC经典架构开发,由Apache推出,在Web开发中流行,主要负责Model和View之间的流程处理,常被用于Struts2中。FreeMarker
一个由Java编写的基于模板生成文本输出的通用工具。被IntelliJ IDE广泛使用于开发工具中,同时适用由IDE衍生的Android Studio中。文件格式 : *.ftl
定义:一种基于模板和要改变的数据,动态生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的工具。
语言:Java
开发工具 :eclipse+[JBoss Tools](http://download.jboss.org/jbosstools/neon/stable/updates/)
> 加载
> 变换(Model<=>View)
> 输出 file
注入对象:${user} FreeMarker将会输出真实的值来替换大括号内的变量,通常称为interpolation(插值)。 ps:<#user>
FTL标签:
1.关键字标签:
<#include>
<merge>
<globals> <global> 全局声明
2.逻辑标签:
<#if condition>
<#list users as user>
3.动作标签:
<recipe> 英文:食谱; 做法
<instantiate frome="" to= ""> 创建【file】
<open file=""> 打开文件【file】
4.自定义标签(Android Studio):
元素:id name type suggest default help
<template> 【模板文件根节点】
<activity>
<fragment>
<category>
<parameter > 【用户界面配置参数】
<thumbs> <thumb>
<dependency /> 【添加依赖库】
<execute file=""> 【执行文件,目标一般为recipe文件】
other:
id = isLauncher 是否为启动activity,会 mainfest的intent-filter 配置启动
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
activityToLayout(activityClass) 根据activity生成layout的名字
目录结构
globals.xml.ftl 【源文件】
template.xml 【用户界面】
template.png 缩略图
root 【未经处理的.ftl源文件】,包含res 和src
recipe.xml.ftl 酿制工序
一键实现RecyclerView.Adapter
这张图会在创建模板的时候左边显示
上述缩略图有了,仍缺少图右界面,其对应文件为template.xml:
<template
format="5"
revision="5"
name="Activity 快速列表"
description="Creates a new application settings activity that presents alternative layouts on handset and tablet-size screens."
minApi="11"
minBuildApi="11"
requireAppTheme="true"
category="Activity">
<dependency name="android-support-v4" revision="8"/>
<category value="Activity(Marshon)"/>
<formfactor value="Mobile"/>
<parameter
id="activityClass"
name="Activity 名称"
type="string"
constraints="class|unique|nonempty"
default="ListActivity"
suggest="${layoutToActivity(activityLayoutName)}"
help="The name of the activity class to create"/>
<parameter
id="activityLayoutName"
name="布局名称(layout):"
type="string"
constraints="layout|unique|nonempty"
suggest="${activityToLayout(activityClass)}"
default="activity_list"
help="The name of the layout to create for the activity" />
<parameter
id="beanName"
name="实体(Bean):"
type="string"
constraints="class|nonempty"
suggest=""
default="Bean"
help="The name of the Bean to create for the Listactivity" />
<parameter
id="isLauncher"
name="是否为启动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"/>
<thumbs>
<thumb>activity_fastlist.pngthumb>
thumbs>
<globals file="globals.xml.ftl"/>
<execute file="recipe.xml.ftl"/>
template>
说明:其中标签和属性的说明在上面语法中有介绍
<globals>
<global id="hasNoActionBar" type="boolean" value="false" />
<global id="parentActivityClass" value="" />
<global id="excludeMenu" type="boolean" value="true" />
<global id="generateActivityTitle" type="boolean" value="false" />
<#include "../common/common_globals.xml.ftl" />
globals>
在这个文件中可以声明本模板使用到的变量,<#include>中还引用了外部声明文件,上述common_globals.xml.ftl 是Android Studio自带的全局变量声明
<recipe>
<#include "../common/recipe_manifest.xml.ftl" />
<#if !appCompat && !(hasDependency('com.android.support:support-v4'))>
<dependency mavenUrl="com.android.support:support-v4:${buildApi}.+"/>
#if>
<#if appCompat && !(hasDependency('com.android.support:appcompat-v7'))>
<dependency mavenUrl="com.android.support:appcompat-v7:${buildApi}.+" />
#if>
<#if (buildApi gte 22) && appCompat && !(hasDependency('com.zhy:base-rvadapter'))>
<dependency mavenUrl="com.zhy:base-rvadapter:3.0.2" />
#if>
<#if appCompat && !(hasDependency('com.android.support:design'))>
<dependency mavenUrl="com.android.support:design:${buildApi}.+" />
#if>
<instantiate from="root/src/app_package/ListActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
<instantiate from="root/src/app_package/Bean.java.ftl"
to="${escapeXmlAttribute(srcOut)}/bean/${beanName}.java" />
<instantiate from="root/res/layout/activity_list.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${activityLayoutName}.xml" />
<instantiate from="root/res/layout/default_loading.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/default_loading.xml" />
<open file="${escapeXmlAttribute(resOut)}/layout/${activityLayoutName}.xml"/>
<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
recipe>
dependency:标签会在build.gradle添加需要的依赖,例你的模板生成的类引用了哪些外部引用
instantiate:加载模板源材料。包含了一些java文件和xml文件。其中语法简单,由原生的java类和xml修改来的。
ListActivity.java.jtl
package ${packageName};
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.RelativeLayout;
import ${packageName}.bean.${beanName};
import com.zhy.adapter.recyclerview.CommonAdapter;
import com.zhy.adapter.recyclerview.base.ViewHolder;
import com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper;
import java.util.ArrayList;
import java.util.List;
/**
* desc fast listactivity
*/
public class ${activityClass} extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener, LoadMoreWrapper.OnLoadMoreListener, View.OnClickListener {
private static int PAGENUM = 1;
private SwipeRefreshLayout mRefreshLayout;
private RecyclerView mRecyclerView;
private LoadMoreWrapper adapter;
private List<${beanName}> mDatas =new ArrayList<>();
// End Of Content View Elements
private void bindViews() {
mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.mRefreshLayout);
mRecyclerView = (RecyclerView) findViewById(R.id.mRecyclerView);
adapter = new LoadMoreWrapper(new CommonAdapter<${beanName}>(${activityClass}.this, R.layout.item_, mDatas) {
@Override
protected void convert(ViewHolder holder, ${beanName} bean, int position) {
//set data in this block
}
});
mRefreshLayout.setOnRefreshListener(this);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
adapter.setLoadMoreView(R.layout.default_loading);
adapter.setOnLoadMoreListener(this);
mRecyclerView.setLayoutManager(new LinearLayoutManager(${activityClass}.this));
mRecyclerView.setAdapter(adapter);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.${activityLayoutName});
bindViews();
}
@Override
public void onRefresh() {
mRefreshLayout.setRefreshing(false);
loadData(PAGENUM);
}
@Override
public void onLoadMoreRequested() {
loadData(++PAGENUM);
}
private void loadData(int pageNum){
}
//Spare. You can delete it by itself.
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id:
break;
case R.id:
break;
}
}
}
上述文件编写完成后,放在同一个文件夹下,最终放到Android Studio模板的文件夹下,模板位置上面四中有描述。放好后重新启动Android Studio,接着创建一个activity试试吧~总体介绍模板开发的基础到这里,在app快速开发时代,模板功能只需简单的配置,即能帮助你一键实现你的基础逻辑代码,一劳永逸,Ctrl、C、V键可已扣。
注意:模板编写编译器是文本编辑器,so没有人告诉你哪句代码写错了会有提示,只能靠人脑先YY预编译。如有错误,Android Studio会提示创建模板失败,但不会告诉你具体Cause by。但是,对于一个熟手来说,你可以在很短时间内创建好你心爱的模板,祝你好运。
模板源码地址:
https://github.com/a371166028/android-studio-template/tree/master/activities/MarshonListActivity