手牵手教你写 IntelliJ Idea 插件:MvpGenerator

  • 2016-10-08
  • 7,438
  • 2

上一篇文章写了:如何将原项目重构成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回复

      是在他的基础上修改的,文中有说到。

发表评论