在享受MVP模式带来的清爽的代码的同时,我们似乎必须忍受写更多的代码,创建更多的文件。
但拥有懒这一优秀品质的程序员,总会为这种困境找到解决的办法。
本文会出现的原因是,lucio在遵循Google的Android MVP示例代码的模式开发一个小的程序,发现我们会需要写很多重复的代码,更加麻烦的是,我们需要创建很多重复的文件。每开发一个小的模块,至少会需要创建Activity、Contract、Fragment和Presenter四个文件。
总之,在享受MVP模式带来的清爽的代码的同时,我们似乎必须忍受写更多的代码,创建更多的文件。
但拥有懒这一优秀品质的程序员,总会为这种困境找到解决的办法。
lucio开始寻找Android Studio的代码自动生成插件,希望有出色的插件能解决我的困境,但结果并不好。相关插件中,很多插件很出色,但它生成的代码结构并不是我期望的——我希望各个小的模块都能自己成为一个包,而不是把整个程序分为几个大的包,前者对我来说有更好的可读性,另外一些插件所生成的代码与我的期望也有许多小的不同。
看过几个插件的源码后,发现开发一个插件并不会很难,于是lucio决定自己写一个插件!
具体的实现思路如下:
- 定义类文件的模板,读取模板,修改关键字后输出类源码
- 使用Intellij IDEA开发插件,提供清爽的可视化界面
生成代码
实现思路
- 写好两个txt文件作为模板
- 读取模板,修改里面不是通用的字段
- 输出生成的代码到指定文件。
模板示例
package &package&;
/**
* Created by xxx on xxxx/xx/xx.
*/
public interface BaseView<T> {
void setPresenter(T presenter);
}
package &package&;
/**
* Created by xxx on xxxx/xx/xx.
*/
public interface BasePresenter {
void start();
}
程序示例
可以看到我们需要修改的只有路径名称这一项,我们只需要读取模板文件,替换全部的&package&为真正的包名。包名的生成,可以取java文件夹下的路径,修改“/”为“.”。
/**
* 获取包名
*/
private String getPackageName(String path) {
return path.substring(path.indexOf("java") + 5, path.length()).replace("/", ".");
}
/**
* 生成BaseView.java
*/
private void genBaseView(String path) {
File codeBaseView = new File(path + "\\base\\" + "BaseView.java");
String strTemplateBaseView = readTemplateFile("BaseView.txt");
String strCodeBaseView = strTemplateBaseView.replaceAll("&package&", getPackageName(path) + ".base");
try {
FileUtils.writeStringToFile(codeBaseView, strCodeBaseView);
} catch (IOException e) {
e.printStackTrace();
}
}
总结
同样的,我们可以生成生成&ModelName&Activity.java、&ModelName&Contract.java、&ModelName&Fragment.java和&ModelName&Presenter.java,做法是相似的,我们只需要更改一些不通用的字段。
如果需要继续扩展,我们还可以让一些工具类的代码也使用自动生成的方式创建。
上面用到的路径,我们期望是点击右键时所在的包下的路径,这在用IDEA开发插件时很容易获取,下面我们看下IDEA开发Android Studio插件的过程。
IDEA开发Android Studio插件
实现过程
- 新建_IntellJ Platform Plugin_项目
- 新建一个Action,设置唤起插件的方式
- 编写插件
我们直接使用Messages类创建对话框,很方便可以不去考虑界面代码的编写,当然如果期望有更好的交互,也可以自己编写界面。下面我们创建了三个对话框分别完成基类、工具类和模块内类文件的自动生成。
程序示例
通过下面的代码获取右键点击位置所在的路径:
project = e.getProject();
selectGroup = DataKeys.VIRTUAL_FILE.getData(e.getDataContext());
String path = selectGroup.getPath();
public class AutoGen extends AnAction {
Project project;
VirtualFile selectGroup;
@Override
public void actionPerformed(AnActionEvent e) {
project = e.getProject();
selectGroup = DataKeys.VIRTUAL_FILE.getData(e.getDataContext());
String path = selectGroup.getPath();
int resultCode = Messages.showYesNoCancelDialog(project,"New base class(BasePresenter.java and BaseView.java)",
"New Base Class", null);
if(resultCode==0) {
GenMVPCode genMVPCode = new GenMVPCode();
genMVPCode.genBaseClassCode(path);
}
int resultCodeUtils = Messages.showYesNoCancelDialog(project,"New utils class(ActivityUtils.java, LogUtils.java and ToastUtils.java)",
"New Base Class", null);
if(resultCodeUtils==0) {
GenMVPCode genMVPCode = new GenMVPCode();
genMVPCode.genUtilsClassCode(path);
}
String modelName = Messages.showInputDialog(project, "Please input model name", "New MVP Model", Messages.getQuestionIcon());
if (modelName == null || modelName.equals("")) {
Messages.showErrorDialog("Model name can not be empty!","Model name is empty.");
return;
}else{
GenMVPCode genMVPCode = new GenMVPCode();
genMVPCode.genModelCode(path,modelName);
}
}
}
试试运行一下,我们可以在指定的路径下生成我们的代码,当然还有一些依赖库和界面文件不存在可能报错,但这已经极大地方便了我们在Android Studio中去创建一个新的模块了。存在的问题我们以后再继续改进。
如果熟悉Java Swing,我们还可以开发出比较好看一点的对话框。当然这个插件还有其他许多可以改进的地方,如检测模块名称是否规范,还可以根据在对话框的输入使用Javapoet在Contract生成方法。这是一个很简单的插件,根据每个人需求不同,可以扩展出不同的用法。
发布插件
为了和更多的人分享我们的成果,我们选择在JetBrains Plugins Repository发布我们的插件。
1.填写plugin.xml的信息
<idea-plugin>
<id>com.luciozhang.plugin.id</id>
<name>MVPAutoGen</name>
<version>1.0</version>
<vendor email="821193666@qq.com" url="http://blog.csdn.net/qq_18738333">luciozhang</vendor>
<description><![CDATA[
A plugin for Android Studio MVP code automatically generating.<br>
<em>https://github.com/zxchehe/MVPAutoGen</em>
]]></description>
<change-notes><![CDATA[
No change notes here.<br>
<em>https://github.com/zxchehe/MVPAutoGen</em>
]]>
</change-notes>
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="145.0"/>
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
</extensions>
<actions>
<!-- Add your actions here -->
<action id="autogen" class="AutoGen" text="AutoGenMVP" description="Automatically generated MVP code">
<add-to-group group-id="NewGroup" anchor="first"/>
</action>
</actions>
</idea-plugin>
注意去掉com.intellij.modules.lang这句的注释让插件可以发布到所有平台,否则只会发布到Intellij Idea。
2.在[JetBrains Plugins Repository]注册账号
3.打包
右键项目名->Prepare Plugin Module ‘xxxx’ For Deployment会生成项目的jar包,有用第三方库的话会生成zip包,也可以直接使用。
4.在官网upload plugin等两个工作日就好了
通过审核后,我们可以在Android Studio中与他人分享到我们的插件。
看看运行效果,基本满足了我们的期望。
文末
我总结了一些Android核心知识点,以及一些最新的大厂面试题、知识脑图和视频资料解析。
需要的小伙伴直接点击文末小卡片免费领取哦,以后的路也希望我们能一起走下去。(谢谢大家一直以来的支持,需要的自己领取)
Android学习PDF+架构视频+面试文档+源码笔记
部分资料一览:
- 330页PDF Android学习核心笔记(内含8大板块)
- Android学习的系统对应视频
- Android进阶的系统对应学习资料
- Android BAT大厂面试题(有解析)
领取地址: