- 原文地址:Supercharging your app development speed with custom file templates
- 原文做者:Rajdeep Singh
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:nanjingboy
- 校对者:tuozhaobing
感谢:Google Inc.,维基共享资源和 Vexelsphp
在 Wishfie 开发 Android 应用时,咱们常常须要编写大量的样板代码以用于建立新的 Activity 和 Fragment。我会举一个例子来讲明个人意思:html
当咱们遵循 MVP 架构时,每一个新增的 Activity 或 Fragment 都须要一个 Contract 类,一个 Presenter 类,一个 Dagger 模板及 Activity 类自身,这致使咱们每次都须要编写大量的类似代码。前端
下面即是咱们的 Activity、Module、Contract 和 Presenter:java
public class DemoActivity extends DemoBaseActivity<DemoContract.Presenter> implements DemoContract.View {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
}
}
复制代码
@Module
public abstract class DemoActivityModule {
@Binds
@PerActivity
abstract DemoContract.Presenter providesPresenter(DemoPresenter demoPresenter);
@Binds
@PerActivity
abstract DemoContract.View providesView(DemoActivity demoActivity);
}
复制代码
public interface DemoContract {
interface View extends DemoBaseContract.ActivityView {
}
interface Presenter extends DemoBaseContract.Presenter {
}
}
复制代码
public class DemoPresenter extends DemoBasePresenter<DemoContract.View> implements DemoContract.Presenter {
@Inject
public DemoPresenter(DemoContract.View view) {
super(view);
}
@Override
public void unSubscribe() {
}
@Override
public void subscribe() {
}
}
复制代码
这是 android 中常见的模式,不少人可能都在使用它。这就是咱们所遇到的问题,它的解决方案来源于 Android Studio 中一个很棒的功能(自定义模板)。linux
在本文的最后,咱们将建立一个根据不一样后缀一次建立全部必须文件的模板。那么,让咱们开始吧:android
Android Studio activity 建立模板ios
IntelliJ 描述以下:git
文件模板是建立新文件时要生成的默认内容规范。根据你建立的文件类型,模板提供了在该类型文件中所预期的初始化代码和格式(根据行业标准,你的公司政策或其余内容)。github
简单来讲,模板用于建立包含一些样板代码的文件。大多数状况下,当你从预约义选项集中建立 Activity、Fragment 和 Service 等文件时,它已经为你编写了许多样板代码,这些代码基本上都是由 Android Studio 团队建立的一组预先编写好的模板建立的。例如,从上图显示菜单建立的 empty activity 默认包含如下样板代码,XML 文件以及 manifest 文件的入口配置。apache
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class EmptyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
}
复制代码
你能够建立 .java、.xml、.cpp 等类型的文件模板。
你能够建立你本身的实时模板。若是你曾经用过 Toast 模板或用于定义 public static final int 的 psfi,这些被称为实时模板。
你能够建立一组文件模板。好比,查看 Android Studio 如何为 Activity 建立 .xml 和 .java 文件,而且在 manifest 文件中添加该 activity 的详细信息。
使用 Apache Velocity Template Language 建立这些模板。
咱们将首先建立一个基本文件模板,该模板将建立一个 RecyclerView Adapter 以及一个内部 ViewHolder 类,由于它是最经常使用的类之一。
咱们将建立咱们本身的实时模板。
咱们将经过编写用于建立上述 4 个文件的模板来结束此操做,以便在咱们的应用中遵循 mvp 架构。
单击 + 按钮建立一个新模板,并将其命名为你想要的任何名称。我将它命名为 RecyclerViewAdapter。
将下面的模板代码粘贴到名称字段下方的区域中。我会一步一步解释代码中发生了什么:
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
#parse("File Header.java")
public class ${NAME} extends RecyclerView.Adapter<${VIEWHOLDER_CLASS}> {
private final Context context;
private List<${ITEM_CLASS}> items;
public ${NAME}(List<${ITEM_CLASS}> items, Context context) {
this.items = items;
this.context = context;
}
@Override
public ${VIEWHOLDER_CLASS} onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.${LAYOUT_RES_ID}, parent, false);
return new ${VIEWHOLDER_CLASS}(v);
}
@Override
public void onBindViewHolder(${VIEWHOLDER_CLASS} holder, int position) {
${ITEM_CLASS} item = items.get(position);
holder.set(item);
}
@Override
public int getItemCount() {
if (items == null){
return 0;
}
return items.size();
}
public class ${VIEWHOLDER_CLASS} extends RecyclerView.ViewHolder {
public ${VIEWHOLDER_CLASS}(View itemView) {
super(itemView);
}
public void set(${ITEM_CLASS} item) {
//UI setting code
}
}
}
复制代码
若是你快速阅读 android studio 中代码输入字段下面的 Description 面板,上面的大部分代码都很容易理解。
${<VARIABLE_NAME>}
用于建立在整个模板中使用的变量,而且当你使用模板建立代码时,系统会提示你为它们输入值。这还有一些预约义的变量,好比 ${PACKAGE_NAME}
,${DATE}
等。
#if
指令用来检查包名是否为空,若是不为空,则将名称添加到做为 ${PACKAGE_NAME}
变量传递的包语句中。
#parse
指令用于插入另外一个名为 File Header.java
模板的内容,你能够在同一窗口的 includes 选项卡下找到该模板。看起来像这样:
其他代码使用这些变量和静态文本,代码和注释来建立文件。
如今右键单击任何目录,而后单击 New,你将在那里找到你的模板。单击它将打开一个提示框,输入咱们以前定义的占位符的值。
package io.github.rajdeep1008.templatedemo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public class SchoolData extends RecyclerView.Adapter<SchoolData> {
private final Context context;
private List<SchoolItem> items;
public SchoolData(List<SchoolItem> items, Context context) {
this.items = items;
this.context = context;
}
@Override
public SchoolData onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.R.layout.item_school, parent, false);
return new SchoolData(v);
}
@Override
public void onBindViewHolder(SchoolData holder, int position) {
SchoolItem item = items.get(position);
holder.set(item);
}
@Override
public int getItemCount() {
if (items == null) {
return 0;
}
return items.size();
}
public class SchoolData extends RecyclerView.ViewHolder {
public SchoolData(View itemView) {
super(itemView);
}
public void set(SchoolItem item) {
//UI setting code
}
}
}
复制代码
使用咱们的 Android Studio 模板生成文件。
这个章节与咱们为 mvp 源文件建立模板的最终目的没什么关系,但知道 Android Studio 为咱们提供的每一个选项是有好处的。
实时模板是你在代码中快速获取代码段的快捷方式。你还能够添加参数来快速标记它们。
在 Android Studio 中播放实时模板。
对于 mac 用户,导航到 Android Studio -> Preferences -> Editor -> Live Templates,在这里你将看到一个包含已有实时模板的列表框,好比 fbc 用于 findViewById 映射,foreach 用于建立 loop 等。
如今点击 Android -> + ->LiveTemplate,你能够选择添加缩写来使用模板,说明模板的功能以及模板的模板文本。
如今点击 Define 并选择弹框中的 XML 选项来选择模板可用的文件类型。
Android Studio 中实时模版建立向导
咱们新建立的实时模板
Pheww!咱们已经介绍了不少东西,如今是时候开始建立咱们的 mvp 模板了。咱们须要建立一个 Activity、DaggerModule、Contract 和 Presenter。前缀将做为用户输入,剩下的将采用本文开头所述的格式。
导航到你的 Windows/Linux/Mac 文件系统中的 Android Studio 目录,而后转到 plugins -> android -> lib -> templates -> other,用你但愿在菜单中看到的名称建立一个空目录,我将其命名为 MVP Template。
在 mac 中,目录的位置应该为 /Applications/Android/Studio.app/Contents/plugins/android/lib/templates/other/,对于 windows 或 linux,你能够在 {ANDROID_STUDIO_LOCATION}/plugins/android/lib/templates/other/ 中找到它。
确保检查模板中的 activities 目录,看看如何模板建立 EmptyActivity、BasicActivity 以及其余文件,这将有助于编写本身的模板。
如今,在新建立的 MVP Template 目录中,建立 template.xml、recipe.xml.ftl 和 globals.xml.ftl。而且建立一个名为 root 的目录,它将保存咱们建立的实际模板文件。我将逐一解释每一个文件的做用:
template.xml — 它用来处理屏幕配置的 UI 部分。 它定义了用户在使用模板建立文件时看到的用户输入字段、复选框和下拉列表等。
recipe.xml.ftl — 这是使用的文件,你的根目录中的模板将转换为 Android Studio 中真实的 java 文件。它包含有关要建立哪些文件以及从哪些模板建立等信息。
globals.xml.ftl — 这包含全部全局变量。在这里为 src 和 res 定义目录路径是一个很好的作法。
<template format="4" revision="1" name="MVP Template Activity" description="Creates a new MVP classes - Presenter, View, Contract and Dagger Module.">
<category value="Other"/>
<parameter id="className" name="Functionality Name" type="string" constraints="class|unique|nonempty" default="MvpDemo" help="The name of the functionality that requires MVP views"/>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
复制代码
template.xml 描述了应该从用户那里得到的参数:
<?xml version="1.0"?>
<recipe>
<instantiate from="src/app_package/Contract.java.ftl" to="${escapeXmlAttribute(srcOut)}/${className}Contract.java" />
<instantiate from="src/app_package/Activity.java.ftl" to="${escapeXmlAttribute(srcOut)}/${className}Activity.java" />
<instantiate from="src/app_package/Presenter.java.ftl" to="${escapeXmlAttribute(srcOut)}/${className}Presenter.java" />
<instantiate from="src/app_package/ActivityModule.java.ftl" to="${escapeXmlAttribute(srcOut)}/${className}ActivityModule.java" />
<open file="${srcOut}/${className}Presenter.java"/>
<open file="${srcOut}/${className}Contract.java"/>
<open file="${srcOut}/${className}Activity.java"/>
<open file="${srcOut}/${className}ActivityModule.java"/>
</recipe>
复制代码
recipe.xml.ftl 定义从哪一个模板建立哪些文件以及建立后打开哪些文件。它还能够将代码从咱们的模板复制到 manifest.xml 或 string.xml 等文件中。请务必查看用于建立 activities 的默认模板示例。
className 变量是咱们从用户那里获取的输入的 id,其代码用 template.xml 编写,srcOut 在 globals.xml.ftl 中定义。文件的其余部分具备很好的自我解释能力。
<?xml version="1.0"?>
<globals>
<global id="resOut" value="${resDir}" />
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
</globals>
复制代码
package ${packageName};
public class ${className}Activity extends DemoBaseActivity<${className}Contract.Presenter> implements ${className}Contract.View {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
}
}
复制代码
package ${packageName};
@Module
public abstract class ${className}ActivityModule {
@Binds
@PerActivity
abstract ${className}Contract.Presenter providesPresenter(${className}Presenter presenter);
@Binds
@PerActivity
abstract ${className}Contract.View providesView(${className}Activity activity);
}
复制代码
package ${packageName};
public interface ${className}Contract{
interface View extends DemoBaseContract.ActivityView {
}
interface Presenter extends DemoBaseContract.Presenter {
}
}
复制代码
package ${packageName};
public class ${className}Presenter extends DemoBasePresenter<${className}Contract.View> implements ${className}Contract.Presenter {
@Inject
public ${className}Presenter(${className}Contract.View view){
super(view);
}
@Override
public void subscribe() {
}
@Override
public void unSubscribe() {
}
}
复制代码
这些文件包含将彻底转换为 java 或 xml 代码的模板,参数将被实际值替换。
咱们终于完成了全部步骤。只须要重启 Android Studio 便可启用此模板,并显示在菜单中。
咱们新建立的 MVP 模板
若是使用得当,Android Studio 模板是加快应用开发速度的强大功能。这些模板能够分布在整个 Android 团队中,以便简化样板代码的建立。
以上即是本文的全部内容。若是你喜欢这篇文章并发现它有用,请不要忘记点赞并与其余 Android 开发者分享它。Happy coding 💗。
顺便说一句,我开通了每周简报 thedevweekly。 我将经过网站、移动设备和系统上精心挑选文章,并在有关新技术学习及一些大科技公司内部学习文章之间取得平衡。
所以,不管你是初学者仍是专家,若是你正在寻找精心策划的科技文章的每周摘要,请在 这里 注册 .
若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。