android studio mvp插件,AndroidStudio插件开发—MVP生成代码插件

简介

之前一篇介绍了如何去开发一个简单的AnroidStudio插件,这一篇详细讲解如何去做一个生成MVP中我们经常重复用到的通用代码插件。

要求

1.根据定义好的Contract.java文件生成对应的Model.java文件,Presenter.java文件,以及构造Contract内部通用代码

2.生成的代码可以被git作为新生成的文件

一:实现Contract内部代码

首先完成Contract内部代码的编写,这里需要了解插件开发的相关API,参考:API

我的mvp是基于T-MVP利用泛型去实现,所以需要用到Model,View,Presenter,另外还有一个用于存放这几个接口Contract契约类,结构如下:

3e1829e3f0bd?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图片.png

至于MVP架构如何设计,网上框架多多,这里主要分析如何去编写插件,老规矩,先新建项目MVPDataBind,t填好常用的几个参数,如下:

3e1829e3f0bd?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图片.png

接着新建一个Action动作,然后在actionPerformed方法中编写,主要实现思路是我们要通过当前获取到的文件得到文件类名,判断文件名是否符合规则,然后通过Document改变当前文件内容:

网上对于Document介绍:Document其实就是Virtual File的内容的字符序列,所以对Document的各种操作都是基于普通文本的。Document的可操作的方法并不多,主要是Document是基于字符序列的,操作起来难度有点大。事实上我们对Document的使用也比较少,通常都是一些信息的简单获取。

代码如下:

private void createContractContent() {

int lastIndex = this.content.lastIndexOf("}");

this.content = this.content.substring(0, lastIndex);

MessagesCenter.showDebugMessage(this.content, "debug");

final String content = this.getContractContent();

WriteCommandAction.runWriteCommandAction(this.editor.getProject(), new Runnable() {

public void run() {

MVPDataBind.this.editor.getDocument().setText(content);

}

});

}

private String getContractContent() {

return this.content.trim() + "\n\n interface View extends BaseView {\n \n }\n\n interface Model extends BaseModel {\n \n }\n\n abstract class Presenter extends BasePresenter {\n \n }\n\n}";

}

然后是我们要先判断操作的当前文件是否合法,命名必须要xxxContract.java:

private boolean checkCanUse() {

this.content = this.editor.getDocument().getText();

String[] words = this.content.split(" ");

String[] var2 = words;

int var3 = words.length;

for (int var4 = 0; var4 < var3; ++var4) {

String word = var2[var4];

if (word.contains("Contract")) {

String className = word.substring(0, word.indexOf("Contract"));

this.classModel.setFunctionName(className);

this.classModel.setClassName(word);

MessagesCenter.showDebugMessage(className, "class name");

}

}

if (TextUtils.isEmpty(this.classModel.getFunctionName())) {

Messages.showErrorDialog(

"文件名定义不规范",

"Error");

// MessagesCenter.showErrorMessage("Create failed ,Can't found 'Contract' in your class name,your class name must contain 'Contract'", "error");

return false;

} else {

return true;

}

}

如果只是Contract,则会弹框报错:

3e1829e3f0bd?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图片.png

到此,我们就实现了编写Contract文件里面的内容,这里要介绍一下

AnActionEvent

AnActionEvent 函数和update函数的形参都包含AnActionEvent对象。AnActionEvent对象是我们与IntelliJ IDEA交互的桥梁,我们可以通过AnActionEvent对象获取当前IntelliJ IDEA的各个模块对象,如编辑框窗口对象、项目窗口对象等,获取到这些对象我们就可以做一些定制的效果。

通过AnActionEvent对象的getData函数可以得到IDEA界面各个窗口对象以及各个窗口为实现某些特定功能的对象。getData函数需要传入DataKey对象,用于指明想要获取的IDEA中的哪个对象。在CommonDataKeys已经定义好各个IDEA对象对应的DataKey对象,不仅仅CommonDataKeys中定义了DataKey对象,为了添加更多的DataKey对象并且兼容等,又提供了PlatformDataKeys类,PlatformDataKeys类是CommonDataKeys子类,也就是说,只要是CommonDataKeys有的,PlatformDataKeys类都有。这里我们通过getData获取到当前的编辑框用于操作编辑框的内容:

this.editor = (Editor) e.getData(PlatformDataKeys.EDITOR);

二.实现新增文件

Contract文件内容编辑好了,接下来就是要通过插件,新建文件了,插件开发中, 使用PSI Files来表示具体操作的文件.参考:https://www.jianshu.com/p/0117d4b1eb00

对于Java来说, 可以通过JavaDirectoryService#createClass(dir, fileName)来创建类文件, 同时会返回一个PsiClass实例表示该类.然后我们定义接口回调,执行后续的类实现和继承等操作,如下:

public void generateFile(final PsiDirectory directory, final String fileName, final String type, final onFileGeneratedListener listener) {

WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {

@Override

public void run() {

PsiClass[] psiClasses = myShortNamesCache.getClassesByName(fileName, myProjectScope);//NotNull

PsiClass psiClass;

PsiJavaFile javaFile;

if (psiClasses.length != 0) {//if the class already exist.

psiClass = psiClasses[0];

javaFile = (PsiJavaFile) psiClass.getContainingFile();

javaFile.delete();//then delete the old one

}//and re-generate one

psiClass = myDirectoryService.createClass(directory, fileName, type);

javaFile = (PsiJavaFile) psiClass.getContainingFile();

PsiPackage psiPackage = myDirectoryService.getPackage(directory);

javaFile.setPackageName(psiPackage.getQualifiedName());

listener.onJavaFileGenerated(javaFile, psiClass);

}

});

这里是生成xxxModel文件的操作,先通过myDirectoryService.createClass(directory, fileName, type)创建类文件,然后通过查询之前定义得xxxContract得到需要实现的Model接口名,最后用add方法加入到新建的类里面,最后通过setModifierProperty设置类的修饰符为public,生成Presenter代码类似,把实现接口变为继承Presenter子类,代码如下:

fileGenerator.generateFile(myCurrentDir, className + "Model", JavaTemplateUtil.INTERNAL_CLASS_TEMPLATE_NAME, new FileGenerator.onFileGeneratedListener() {

@Override

public void onJavaFileGenerated(PsiJavaFile javaFile, PsiClass psiClass) {

PsiClass contractClass = fileGenerator.myShortNamesCache.getClassesByName(fileGenerator.myPrefix + "Contract", fileGenerator.myProjectScope)[0];

PsiClass model = contractClass.findInnerClassByName("Model", false);//don't need to search base

psiClass.getImplementsList().add(fileGenerator.myFactory.createClassReferenceElement(model));

psiClass.getModifierList().setModifierProperty("public", true);//force 'public interface myPrefixContract'

}

});

fileGenerator.generateFile(myCurrentDir, className + "Presenter", JavaTemplateUtil.INTERNAL_CLASS_TEMPLATE_NAME, new FileGenerator.onFileGeneratedListener() {

@Override

public void onJavaFileGenerated(PsiJavaFile javaFile, PsiClass psiClass) {

PsiClass contractClass = fileGenerator.myShortNamesCache.getClassesByName(fileGenerator.myPrefix + "Contract", fileGenerator.myProjectScope)[0];

PsiClass model = contractClass.findInnerClassByName("Presenter", false);//don't need to search base

psiClass.getExtendsList().add(fileGenerator.myFactory.createClassReferenceElement(model));

psiClass.getModifierList().setModifierProperty("public", true);//force 'public interface myPrefixContract'

}

});

文件创建完成之后编译打成jar包,导入AndroidStudio测试效果如下:

3e1829e3f0bd?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

GIF.gif

基本达到了我们的需求

总结:

对于MVP架构,插件生成我们的常用契约类,对开发效率还是有一定的提升,免去了我们重复建类,命名的问题,不过文件的读写,创建只是插件开发的一点点,要想熟练插件开发,还需要阅读官方文档Api,多参考别人的插件开发实现原理,最后附上插件源码github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值