规范你的代码:AndroidStudio 一键生成MVP模板代码

题外话

很久之前就了解过Google的 todo-mvp开发模式,但很长一段时间都不想用于实际项目中。主要原因就是感觉很麻烦。因为那时我用的开发模式是MVC,我理解的MVC很简单:布局文件表示View、Activity表示Control,然后我只需新建一个类作为Model就可以了,什么脏活累活都放在Model处理,完了之后刷新布局。我的目的也很简单:保证我的Activty整洁干净...然而功能复杂后会让单薄的Model变得杂乱不堪~

相比MVC,以todo-mvp为例你新建一个MVP的Activty你还要建相关的 View、Model、Presenter、Contract等等的类和接口,而且各个类、接口间的继承和实现,眼花缭乱啊!这真的让刚接触的人望而止步,新增一个Activity都那么费劲了,如果一个项目下来会不会变得很臃肿?而且会额外新增巨大的工作量,种种担忧让我一直将MVP拒之门外,但随着项目越来越大,功能越来越复杂 MVC出现了明显的短板。再讲下去就有点跑题了,关于MVC和MVP的对比可以参考一下浅谈MVC、MVP。到这可能有孩子想说了:"别人都用MVVM了,你还用MVP,太low了!"。就像找媳妇一样,不是哪个漂亮就去娶谁,别人也不一定看得上你,合适的才是最重要的。

纯洁的微笑

入正题

于是就一直琢磨着能不能在新建一个Activity的同时生成MVP所需要的所有类和接口。网上搜索一番,发现了Android Studio中自定义模板。因为对todo-mvp不太感冒于是参考了Android简单实用的MVP框架
实现了以rxjava全家桶+retrofit+butterknife+eventbus+glide为技术栈的MVP模板。

\color{red}{注意!本教程是以Create New Mvp Project为基础。}因为在Create New Mvp Project的时候我会把retrofit和rxjava等用到的框架进行依赖,而且会把所有封装的类如:retrofit工厂类、工具类等等常用的类导入进来,重点是把mvp的基类导入了进来供其他自定义模板使用。由于另外两个模板需要用到相关的框架和自定义类,所以必须要先用Create New Mvp Project这个模板创建项目。这样做目的主要是为了让大家快点看到效果,同时给大家一点灵感,从而创建出属于自己的一套模板,规范自己的代码,提高开发效率,早点下班!

直接上效果图(本人PS功底一般,模板的封面图就先随意放了)


创建MVP项目
新建MVP模板代码

1.新建一个项目

image

2.选择模板

image

3.设置参数

这里要注意的是你只需要填入 Input Your Name(开发者)和File Head Name(生成所有类的名称),其他的不用管,不要去修改Activity Name和Layout Name! 然后直接finish创建新项目。关于参数后面详解。

image

4.生成MVP工程

生成MVP工程的同时会把你技术栈所用到的依赖添加进来,也包括常用的工具类、资源文件(自定义布局、动画文件、values下的所有配置文件等等),只要你用到的基本都能添加进来。如果你是一位经常要开发新项目的猿,此时是不是想喊我baba了。不用一块砖一块砖般过来了,一键新建项目后直接干就完了!如下图就是刚新建了工程的样子,这是我常用的工程结构。不用像以前那样新建项目后从其它项目把代码复制粘贴过来了,省心!

image

5.新建一个新的MVP Activity或者 Fragment

注意!注意!注意!我定义的所有路径都是基于包名下的!!新建时一定要右击包名,然后选择自定义的模板!这里不要选Create New Mvp Project模板了这个是新建工程的,选Create New Mvp Activity Or Fragment或者RecyclerView Activity用于生成MVP模式的Activity或Fragment

image

6.填写新增模块的参数

这里也只是修改Your Name和Component Name就可以了,然后选择新建Activity还是Fragment 然后点击finish即可。

image

7.生成新的MVP模块

下图是新增了一个MVP Activity模板的样子,是不是轻轻松松就让项目规范了起来?一键生成mvp模式的代码不用做重复无用的工作,只用关心你的业务。

image

到这里效果基本就演示完了,因为新建项目时就依赖了相关的框架和导入了封装好的类,所以可以直接进行网络请求如图:

image

本人同时还另外还制作了RecyclerView Activity,相信大家使用RecyclerView都会觉得有点烦,又要新建一个adapter,又要新建列表里的子布局、数据的实体类。如果是分页列表的更烦,copy一堆接口和实现逻辑,现在可以一键生成是不是很爽?好了,讲那么多开始讲教程了,主要让大家会自己建立一个符合自己编码习惯的模板。我的模板只作抛砖引玉之用。


纯洁的微笑

第一步找到模板文件夹

在你Android Studio安装目录下找到 \templates\activities这个目录,可以看到这里面有很多自带的模板。而我们要做的就是选一个最简单最干净的模板copy在当前文件夹,重命名后进行改造。如果你有其他的模板,直接拷贝到这个目录下重启IDE即可使用。

image

第二步拷贝EmptyActivity模板

image
    然后按你们的想法把拷贝的这个模块重命名,接下来就可以进行改造了。先介绍这几个文件:

root:存放要导入的代码和资源文件。

globals.xml.ftl顾名思义是定义全局参数。

recipe.xml.ftl主要负责把root里面的文件导入到项目里。

template.xml主要负责定义新建模板时所需的参数。

template_blank_activity.png是模板的封面图片。

第三步修改模板参数文件template.xml

image
image
image

这里我觉得最需要注意的地方就是<parmeter>标签里的id参数,其他地方需要用到这个<parmeter>的值只需要写${id}即可引用,如我要用到id="componentName"的值只需要引用这个值得地方写${componentName}即可。而且我们可以在recipe.xml和代码、资源文件中使用。

第四步建立需要生成的资源文件

这里我用Create New Mvp Project的root讲解:

image

我们要导入的类都放在root/src/app_package下, \color{red}{注意!这里文件都必须以.ftl 结尾才能配合脚本命令执行相关的操作。}这里我建议事先写好一个可以运行的Android 模板 Demo然后再一个一个修改移植到这个目录。第一步将要移植的文件加上.ftl,第二部打开文件修改里面的包名、类名等,不然新建出来的模板会飘红。

image

如图,我们需要用freemarker语法定义包名类名,确保生成文件的位置和你定义的是一致的。这里用到的值都是我们之前在template.xml中定义的。上面我说过,如果要在工程新建mvp模板的Activity,必需是右击项目的包名新建。看上图第一行:package ${packageName}.activity意思就是在当前的包名下的activity文件夹内新建一个Activity,所以一定要在该包名上操作,或者自行定义,其他文件的定义也是一样。这里要说一下引用template.xml中的值时可能要进行判断,这时可以用

<#if 条件>

执行A

<#else>

否则执行B

</#if>

举个例子:比如你需要根据新建模板时获取的参数来创建不同的布局可以这样写:

<#if 条件>

setContentView(R.layout.activity_A);

<#else>

setContentView(R.layout.activity_B);

</#if>

在你的代码文件或者recipe.xml.ftl中都可以使用。

还有其他很多方法大家可以去发掘,鄙人能找到的这方面资料太少。

除了添加代码还可以添加AndroidManifest.xml,build.gradle还有res下的anim、layout、drawable、values等文件夹所以功能很是强大。

先说说比较简单的res

image

像anim、drawable、layout、values这些资源问件一般直接拷贝过来就可以使用了,连.ftl后缀都不用添加在recipe.xml.ftl直接写copy把整个文件夹都拷贝到项目里就行,但是你如果想要对里面的文件进行操作的话,那个文件就必须加上.flt不然脚本语言无法执行文件而导致报错。

提醒一下AndroidManifest.xml,build.gradle这两个文件,其实自己写常用模板时很少会用到一般是新建项目的模板才会用到,因为坑很多所以有必要记录下:在新建一个项目时,系统的公共模板文件就已经定义好这两个文件了,如果想修改这两个文件目前我想到的有三种方法:
(1)修改系统公共模板文件,但会影响所有的模板,难度太大风险太高不建议。
(2)直接用自己写的AndroidManifest、build替换系统生成的文件,尝试了很多次都是报错,最抓狂的是他不提示你具体哪里错了,而是谈谈的来一句“兄dai,报错了”。所以无法继续进行。
(3)用merge把内容写入这两个文件。可以成功运行,但有坑。
,AndroidManifest.xml里主要就是想添加权限,但是这里就出现了问题。如果有解决的方法的同学请赐教,本人琢磨了很久,因为找不到相关资料就不停的去尝试。发现在AndroidManifest.xml中只添加一条权限时时没问题的,但是添加多条权限后生成的代码格式就乱了,还有就是build.gradle里依赖多个库没问题,但要想在android {}添加多行配置就出现问题了。目前解决的方法还是一行一行的添加配置。比如我要在android {}里添加

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

这里就要分两次merge进gradle里面 ,如下图

image

我要建立一个文件a内容是:

android {

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
}

}

文件b内容是:

android {

compileOptions {
    targetCompatibility JavaVersion.VERSION_1_8
  }

}

通过这两个文件我才能把把内容merge进build.gradle里面。有点复杂不推荐这样做,我这是为了整体效果采用的极端方式。当然我最希望是把所有配置和依赖写入build.gradle然后导进去就好了,但是均已失败告终。原因可能很多,一是资料太少无法深入研究,基本都是靠参考系统自带的模板 进行学习。二是可能这方面的功能不是很稳定,因为我用的是3.1.3版本的AndroidStudio,把运行完美的模板交给了使用2.1的朋友结果报错了,里面的坑还是多哈。

上面已经准备好了生成模板的资源,现在就准备把这些资源按我们定义生成在项目里。这时就要用到recipe.xml这个文件了。

image

这里主要是用到了3个标签将我们定义好的文件生成在项目里

1.merge合并,把你的资源文件的内容合并到目标文件。像AndroidManifest.xml和build.gradle只能用merge,如果想直接替换文件里面有很多问题要处理。公共模板文件里面有很多文件相互调用,而且都是用脚本语言、宏定义写的,水平有限就只能用水平有限的方法处理了。

2.copy拷贝,顾名思义就是把你的资源文件直接拷贝到对应的路径下了。

3.instantiate 实例,使用后加上个人理解应该是资源文件在对应的路径下生成一个实例。

其中关于路径我都是参考系统其他模板里面定义的,其中

${escapeXmlAttribute(manifestOut)}表示AndroidMainfest.xml所在目录;

${escapeXmlAttribute(projectOut)}表示项目下的app文件夹路径,和src文件夹同一层级

${escapeXmlAttribute(resOut)}表示资源文件的根目录即res文件夹

${escapeXmlAttribute(srcOut)}表示表示项目代码文件的根目录

最后open标签建新模板后AndroidStudio打开目标文件。

我刚开始写recipe.xml的时候在想怎么在工程里新建一个目录,然后我再把代码文件导入到我新建的目录。后来发现并不需要那么麻烦

<instantiate from="root/src/app_package/ModelImple.java.ftl"      to="${escapeXmlAttribute(srcOut)}/implement/${componentName}ModelImple.java" />

 to="${escapeXmlAttribute(srcOut)}/implement/${componentName}ModelImple.java"

中,implement代表路径,只要你写上路径就会为你直接生成相应的文件夹。

到这基本就结束了,这里是代码地址,只需要把模板文件放在\Android Studio\plugins\android\lib\templates\activitie下即可使用,有问题欢迎指出,也欢迎转载,请注明出处,谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容