Android Studio模板开发基础教程

一、案例

  • 修改项目包名
  • 设计模式
  • 通用功能
  • 工程构建

二、目的

避免重复造砖,快速构建简单重复的代码工作。

三、FreeMark介绍

1.为什么是FreeMarker?

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/)

2.工作原理

> 加载
> 变换(Model<=>View)
> 输出 file

Android Studio模板开发基础教程_第1张图片

case:
Android Studio模板开发基础教程_第2张图片

3.简单语法

注入对象:${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的名字

四、Android Studio模板

1.模板组件

  • 位置
    */{Android Studio}/Contents/plugins/android/lib/templates/
  • 目录结构

    globals.xml.ftl 【源文件】

    template.xml 【用户界面】

    template.png 缩略图

    root 【未经处理的.ftl源文件】,包含res 和src
    recipe.xml.ftl 酿制工序

2.模板类

  • 位置
    */Users/${user}/Library/Preferences/AndroidStudio2.3/fileTemplates

3.模板组件操作步骤

一键实现RecyclerView.Adapter

3.1 准备一张门面图 activity_fastlist.png


这张图会在创建模板的时候左边显示

3.2 编写界面 template.xml

Android Studio模板开发基础教程_第3张图片
上述缩略图有了,仍缺少图右界面,其对应文件为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>

说明:其中标签和属性的说明在上面语法中有介绍

3.3 全局声明 globals.xml.ftl


<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自带的全局变量声明

3.4 生成模板


<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

你可能感兴趣的:(Android技术集锦)