文件组模板是基于FreeMarker模板语言的一个功能很强大的Android开发模板,可以这样说,代码片段模板和文件模板是一种提高编码效率的工具,而文件组模板可以算是一种模板引擎。
在网站设计、成都网站设计中从网站色彩、结构布局、栏目设置、关键词群组等细微处着手,突出企业的产品/服务/品牌,帮助企业锁定精准用户,提高在线咨询和转化,使成都网站营销成为有效果、有回报的无锡营销推广。成都创新互联专业成都网站建设10多年了,客户满意度97.8%,欢迎成都创新互联客户联系。
效果图展示
已有工程中使用模板效果图
创建工程时使用模板
示例场景
在进行Android开发时,我们经常会创建一个Demo工程,目的可能有很多种,可能是为了验证一个问题,可能是为了学习一个框架的使用,可能为了测试自己写的一个lib库等等。这个时候我们可能会创建一个Activity,然后再在xml写一些按钮,再在Activity里写该按钮的事件监听逻辑,也就是说为了执行一段代码我们要做这么多操作。为了简化这段重复操作,我这边写了一个DebugActivity类,然后支持我们只需要写个子类来继承它,然后像下面这样写几个方法即可,运行的时候会根据方法动态创建按钮,并在点击按钮时执行该方法的代码逻辑。
- public void _test() {
- T("弹出Toast");
- }
由于本文主要介绍模板相关的,所以该场景相关的具体代码技术细节就不多说了,有兴趣的可以看下,DebugActivity的代码,这里提出来只是为模板开发简单的做个铺垫。
模板位置
Android Studio Template中有系统预设的一些模板,我们可以直接修改,也可以另行添加新的模板。打开Android Studio安装目录/Contents/plugins/android/lib/templates这个文件夹我们能看到下面的目录结构,这里便是AS中模板存放的位置。
我们接下来的工作也就在这里,保险起见我们在这里新建一个目录,我们自己写的模板都放在自己新建的目录里,例如我这里就创建了一个叫pk的目录。
模板规范
在上面的基础上,我们可以直接打开/activies/EmptyActivity目录,如下图
我们可以看到上面红色区域便是Template的文件结构,大致说下各个文件(夹)的含义
我们可以看到,真正核心的部分就是root、recipe.xml.ftl和template.xml,接下来这重点说明这三部分。
我们可以打开root目录,能够看到里面的文件除了图片资源文件都是以.ftl结尾的,而.ftl是标准的FreeMarker的文件。FreeMarker是类似于Velocity的一种模板框架,据说对于多文件处理时它具有更好的性能,大概也是Android Studio选择Velocity作为单文件模板,选择FreeMarker作为文件组模板的原因吧。有兴趣的可以去FreeMarker官网学习一下,它的自定义标签功能还是很强大的,个人感觉比Velocity的更加接地气。
接下来我们看一下recipe.xml.ftl 的内容,打开如下
这里以<#开头的都是FreeMarker的语法,基本上比葫芦画瓢就能看明白,就不多说了。其实对于这个文件最重要的部分是下面四个标签:
然后看下template.xml内容
- format="5"
- revision="5"
- name="Empty Activity"
- minApi="7"
- minBuildApi="14"
- description="Creates a new empty activity">
- 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" />
- id="generateLayout"
- name="Generate Layout File"
- type="boolean"
- default="true"
- help="If true, a layout file will be generated" />
- 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" />
- 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" />
- id="packageName"
- name="Package name"
- type="string"
- constraints="package"
- default="com.mycompany.myapp" />
template_blank_activity.png
当我们进行模板引入时,AS会弹出一个如下图的UI界面,要我们来填入或选择一些数据,例如输入Activity的的名称,选择SDK的版本之类的。而这个界面就是根据由该文件而来的。
内容比较多,为减少篇幅我挑些重要的说
操刀实战
了解了模板规范之后,我们编写模板时就不会那么被动了,下面我们来自己动手编写文章开始部分展示的模板。
首先在刚才提到的自定义的模板下创建如下图所示的目录结构
然后将下面的代码对应贴进去(图片部分随便找一张代替好了…)
globals.xml.ftl
recipe.xml.ftl
template.xml
- format="5"
- revision="5"
- name="Debug Activity"
- minApi="7"
- minBuildApi="14"
- description="创建一个Debug的Activity">
- id="activityClass"
- name="Activity名称"
- type="string"
- constraints="class|unique|nonempty"
- default="SetupActivity"
- help="创建Activity的名称" />
- id="addExample"
- name="是否添加按钮使用示例"
- type="boolean"
- default="false"
- help="选择时会自动生成测试按钮;否则不生成" />
- id="addJumpActivity"
- name="是否添加跳转Activity示例"
- type="boolean"
- default="false"
- help="选择时会自动生成跳转Activity相关逻辑;否则不生成" />
- id="isLauncher"
- name="设为启动页面"
- type="boolean"
- default="true"
- help="选择时设置该页面为启动页面;否则不设" />
- id="packageName"
- name="包名"
- type="string"
- constraints="package"
- default="com.mycompany.myapp"
- help="输入Application包名" />
template_debug_activity.png
AndroidManifest.xml.ftl
DebugActivity.java.ftl
- package ${packageName};
- import android.app.Activity;
- import android.content.Context;
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.LinearLayout;
- import android.widget.ScrollView;
- import android.widget.Toast;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Debug测试类,快速调试Demo工程
- * 使用姿势:
- * 1. 新建一个子类继承该类
- * 2. 跳转Activity: 在子类配置{@link Jump}注解, 然后在注解中配置跳转Activity的类型
- * 3. 点击按钮触发方法: 在子类声明一个名称以"_"开头的方法(支持任意修饰符),最终生成按钮的文字便是改方法截去"_"
- * 4. 方法参数支持缺省参数和单个参数
- * 5. 如果是单个参数,参数类型必须是Button或Button的父类类型,当方法执行时,该参数会被赋值为该Buttom对象
- * https://github.com/puke3615/DebugActivity
- *
- *
- * @author zijiao
- * @version 16/10/16
- */
- public abstract class DebugActivity extends Activity {
- protected static final String FIXED_PREFIX = "_";
- private final String TAG = getClass().getName();
- private final List
buttonItems = new ArrayList<>(); - protected LinearLayout linearLayout;
- protected Context context;
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Jump {
- Class extends Activity>[] value() default {};
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- this.context = this;
- ScrollView scrollView = new ScrollView(this);
- setContentView(scrollView);
- this.linearLayout = new LinearLayout(this);
- this.linearLayout.setOrientation(LinearLayout.VERTICAL);
- scrollView.addView(linearLayout);
- try {
- resolveConfig();
- createButton();
- } catch (Throwable e) {
- error(e.getMessage());
- }
- }
- private void createButton() {
- for (ButtonItem buttonItem : buttonItems) {
- linearLayout.addView(buildButton(buttonItem));
- }
- }
- protected View buildButton(final ButtonItem buttonItem) {
- final Button button = new Button(this);
- button.setText(buttonItem.name);
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (buttonItem.target != null) {
- to(buttonItem.target);
- } else {
- Method method = buttonItem.method;
- method.setAccessible(true);
- Class>[] parameterTypes = method.getParameterTypes();
- int paramSize = parameterTypes.length;
- switch (paramSize) {
- case 0:
- try {
- method.invoke(DebugActivity.this);
- } catch (Throwable e) {
- e.printStackTrace();
- error(e.getMessage());
- }
- break;
- case 1:
- if (parameterTypes[0].isAssignableFrom(Button.class)) {
- try {
- method.invoke(DebugActivity.this, button);
- } catch (Throwable e) {
- e.printStackTrace();
- error(e.getMessage());
- }
- break;
- }
- default:
- error(method.getName() + "方法参数配置错误.");
- break;
- }
- }
- }
- });
- return button;
- }
- private void resolveConfig() {
- Class> cls = getClass();
- //读取跳转配置
- if (cls.isAnnotationPresent(Jump.class)) {
- Jump annotation = cls.getAnnotation(Jump.class);
- for (Class extends Activity> activityClass : annotation.value()) {
- buttonItems.add(buildJumpActivityItem(activityClass));
- }
- }
- //读取方法
- for (Method method : cls.getDeclaredMethods()) {
- handleMethod(method);
- }
- }
- protected void handleMethod(Method method) {
- String methodName = method.getName();
- if (methodName.startsWith(FIXED_PREFIX)) {
- methodName = methodName.replaceFirst(FIXED_PREFIX, "");
- ButtonItem buttonItem = new ButtonItem();
- buttonItem.method = method;
- buttonItem.name = methodName;
- buttonItems.add(buttonItem);
- }
- }
- protected ButtonItem buildJumpActivityItem(Class extends Activity> activityClass) {
- ButtonItem buttonItem = new ButtonItem();
- buttonItem.name = "跳转到" + activityClass.getSimpleName();
- buttonItem.target = activityClass;
- return buttonItem;
- }
- public void L(Object s) {
- Log.i(TAG, s + "");
- }
- public void error(String errorMessage) {
- T("[错误信息]\n" + errorMessage);
- }
- public void T(Object message) {
- Toast.makeText(context, String.valueOf(message), Toast.LENGTH_SHORT).show();
- }
- public void to(Class extends Activity> target) {
- try {
- startActivity(new Intent(this, target));
- } catch (Exception e) {
- e.printStackTrace();
- error(e.getMessage());
- }
- }
- public void T(String format, Object... values) {
- T(String.format(format, values));
- }
- protected static class ButtonItem {
- public String name;
- public Method method;
- public Class extends Activity> target;
- }
- }
JumpActivity.java.ftl
SimpleActivity.java.ftl
- package ${packageName};
- @DebugActivity.Jump({
- <#if addJumpActivity>
- JumpActivity.class,
- <#else>
- #if>
- })
- public class ${activityClass} extends DebugActivity {
- <#if addExample>
- private int number = 0;
- public void _无参方法调用() {
- T("无参方法调用");
- }
- public void _有参方法调用(Button button) {
- button.setText("number is " + number++);
- }
- //代码执行不到,直接弹出toast提示报错
- public void _错误参数调用(String msg) {
- T("test");
- }
- //方法名没有以"_"开头,按钮无法创建成功
- public void 无效调用() {
- T("test");
- }
- //crash会被会被catch住,以toast方式弹出
- public void _Crash测试() {
- int a = 1 / 0;
- }
- #if>
- }
ok,到此对于该模板的编写过程就结束了,接下来重启下Android Studio,然后New Project一路next下去,直到这个界面,这里就是我们自定义的DebugActivity模板了
网页名称:AndroidStudio模板之文件组
转载源于:http://www.csdahua.cn/qtweb/news43/124343.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网