手牵手教你写 IntelliJ Idea 插件:MvpGenerator
上一篇文章写了:如何将原项目重构成MVP模式
实际使用中发现每次新建一个页面,都需要另外建三个类,分别是Contract,Model,Presenter,着实是一项枯燥无味的体力活。
当遇到这种事情的时候,最先想到的就是能不能写一段代码来做这件事。
上网一搜,果然已经有人做好了:Android Studio插件之MVPHelper,一键生成MVP代码,非常感谢这位大兄弟。
赶紧按他的步骤试了一遍,发现不太适应自己的项目,所以决定在他的基础上简化了一版,网上找了一下关于IntelliJ Idea插件开发的资料,发现不太多,
先推荐一个Hello Word版:自己动手写IDEA plugin – PubEditor (1) Hello, world
上项目github地址:https://github.com/pqpo/MvpGenerator
主要类:MvpGeneratorAction.java
package pw.qlm.mvpgenerator;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* mvp 模板代码生成器
* Created by Qiu Linmin on 2016/9/30.
*/
public class MvpGeneratorAction extends AnAction {
public void actionPerformed(AnActionEvent e) {
Editor editor = e.getData(PlatformDataKeys.EDITOR);
if (editor == null) {
return;
}
String content = editor.getDocument().getText();
String className = getClassName(content);
if (className == null) {
Messages.showMessageDialog("Create failed ,Can't found 'Contract' in your class name,your class name must contain 'Contract'", "Error", Messages.getErrorIcon());
return;
}
String currentPath = getCurrentPath(e);
if (currentPath == null || !currentPath.contains("contract")) {
Messages.showMessageDialog("Your Contract should in package 'contract'.", "Error", Messages.getErrorIcon());
return;
}
String basePath = currentPath.replace("contract/" + className + ".java", "");
String basePackage = getPackageName(basePath);
String modelName = className.substring(0, className.indexOf("Contract"));
String contractContent = String.format(MvpTemplate.CONTRACT_TEMPLATE, basePackage, modelName);
WriteCommandAction.runWriteCommandAction(editor.getProject(), () -> editor.getDocument().setText(contractContent));
try {
createPresenterClass(basePackage, basePath, modelName);
createModelClass(basePackage, basePath, modelName);
} catch (IOException e1) {
Messages.showMessageDialog("create file failed", "Error", Messages.getErrorIcon());
return;
}
Messages.showMessageDialog("created success! please wait a moment", "Success", Messages.getInformationIcon());
refreshProject(e);
}
private String getClassName(String content) {
String[] words = content.split(" ");
for (String word : words) {
if (word.contains("Contract")) {
return word;
}
}
return null;
}
private void refreshProject(AnActionEvent e) {
e.getProject().getBaseDir().refresh(false, true);
}
private void createModelClass(String basePackage, String path, String modelName) throws IOException {
String dir = path + "model/" ;
String filePath = dir + modelName + "Model.java";
File dirs = new File(dir);
File file = new File(filePath);
if (!dirs.exists()) {
dirs.mkdirs();
}
file.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
String content = String.format(MvpTemplate.MODEL_TEMPLATE, basePackage, modelName, modelName);
writer.write(content);
writer.flush();
writer.close();
}
private void createPresenterClass(String basePackage, String path, String modelName) throws IOException {
String dir = path + "presenter/";
String filePath = dir + modelName + "Presenter.java";
File dirs = new File(dir);
File file = new File(filePath);
if (!dirs.exists()) {
dirs.mkdirs();
}
file.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
String content = String.format(MvpTemplate.PRESENTER_TEMPLATE, basePackage, modelName, modelName, modelName, modelName);
writer.write(content);
writer.flush();
writer.close();
}
private String getPackageName(String path) {
String[] strings = path.split("/");
StringBuilder packageName = new StringBuilder();
boolean packageBegin = false;
for (int i = 0; i < strings.length; i++) {
String string = strings[i];
if ((string.equals("com")) || (string.equals("org")) || (string.equals("cn")) || (string.equals("pw"))) {
packageBegin = true;
}
if (packageBegin) {
packageName.append(string);
if (i != strings.length - 1) {
packageName.append(".");
}
}
}
return packageName.toString();
}
private String getCurrentPath(AnActionEvent e) {
VirtualFile currentFile = DataKeys.VIRTUAL_FILE.getData(e.getDataContext());
if (currentFile != null) {
return currentFile.getPath();
}
return null;
}
}
MvpTemplate.java
package pw.qlm.mvpgenerator;
interface MvpTemplate {
String CONTRACT_TEMPLATE =
"package {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}s.contract;\n" +
"\n" +
"/**\n * Created by MvpGenerator.\n */\n" +
"public interface {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sContract {\n" +
"interface View extends IView {\n" +
"}\n" +
"\n" +
"interface Presenter extends IPresenter<View> {\n" +
"}\n" +
"\n" +
"interface Model extends IModel {\n" +
"}\n" +
"}";
String PRESENTER_TEMPLATE = "package {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}s.presenter;\n" +
"\n" +
"/**\n * Created by MvpGenerator.\n */\n" +
"public class {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sPresenter extends BasePresenter<{936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sContract.View, {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sContract.Model> implements {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sContract.Presenter {\n" +
"}";
String MODEL_TEMPLATE = "package {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}s.model;\n" +
"\n" +
"/**\n * Created by MvpGenerator for CreditCard.\n */\n" +
"public class {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sModel implements {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}sContract.Model {\n" +
"}";
}
如果不符合自己项目的需求,小伙伴们可以修改MvpTemplate类来简单的定制,整个项目也没几行代码,重新撸一个也不是难事。
>> 转载请注明来源:手牵手教你写 IntelliJ Idea 插件:MvpGenerator赏
免费分享,随意打赏
SheepYang
wing神
pqpo
是在他的基础上修改的,文中有说到。