如今我们开发通常采用MVP模式,在逻辑清晰,分工明确的好处下,也带来了一些弊端,每次创建一个Activity,都需要创建2~3个类或者接口来进行分工,既然是这样,每次都需要重复的建相同类型(Presenter,Contract)的类,何不自己开发一个这样的插件呢。
开发插件使用的工具为IntelliJ IDEA。
安装完成新建工程
注意箭头指向的2个地方不选错就可以了,关于JDK的话,选一个自己电脑安装的就可以了,我选的1.8.
新建完成的目录,其中 plugin.xml 相当于我们的 AndroidManifest.xml,对一些Actions(类似于我们的Activity)进行注册,逻辑代码同样写在 src 中,资源文件(比如说icon)放在 resources 中。
核心Action
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import java.io.*;
/**
* Description: AndroidMvpAction需要在“plugin.xml”注册
* Author: djs
* Date: 2019/5/28.
*/
public class AndroidMvpAction extends AnAction {
Project project;
VirtualFile selectGroup;
@Override
public void actionPerformed(AnActionEvent e) {
project = e.getProject();
String className = Messages.showInputDialog(project, "请输入类名称", "NewMvpGroup", Messages.getQuestionIcon());
selectGroup = DataKeys.VIRTUAL_FILE.getData(e.getDataContext());
if (className == null || className.equals("")) {
System.out.print("没有输入类名");
return;
}
if (className.equals("mvp") || className.equals("MVP") || className.equals("Mvp")) {
createMvpBase();
} else {
createClassMvp(className);
}
project.getBaseDir().refresh(false,true);
}
/**
* 创建MVP的Base文件夹
*/
private void createMvpBase() {
String path = selectGroup.getPath() + "/mvp";
String packageName = path.substring(path.indexOf("java") + 5, path.length()).replace("/", ".");
String presenter = readFile("BasePresenter.txt").replace("&package&", packageName);
String presenterImpl = readFile("BasePAV.txt").replace("&package&", packageName);
String view = readFile("BaseView.txt").replace("&package&", packageName);
String activity = readFile("BaseActivity.txt").replace("&package&", packageName);
String fragment = readFile("BaseFragment.txt").replace("&package&", packageName);
writetoFile(presenter, path, "BasePresenter.java");
writetoFile(presenterImpl, path, "BasePresenter.java");
writetoFile(view, path, "BaseView.java");
writetoFile(activity, path, "BaseActivity.java");
writetoFile(fragment, path, "BaseFragment.java");
}
/**
* 创建MVP架构
*/
private void createClassMvp(String className) {
boolean isFragment = className.endsWith("Fragment") || className.endsWith("fragment");
if (className.endsWith("Fragment") || className.endsWith("fragment") || className.endsWith("Activity") || className.endsWith("activity")) {
className = className.substring(0,className.length() - 8);
}
String path = selectGroup.getPath() + "/" + className.toLowerCase();
String packageName = path.substring(path.indexOf("java") + 5, path.length()).replace("/", ".");
String mvpPath = FileUtil.traverseFolder(path.substring(0, path.indexOf("java")));
mvpPath=mvpPath.substring(mvpPath.indexOf("java") + 5, mvpPath.length()).replace("/", ".").replace("\\",".");
className = className.substring(0, 1).toUpperCase() + className.substring(1);
System.out.print(mvpPath+"---"+className+"----"+packageName);
String contract = readFile("Contract.txt").replace("&package&", packageName).replace("&mvp&", mvpPath).replace("&Contract&", className + "Contract");
String presenter = readFile("Presenter.txt").replace("&package&", packageName).replace("&mvp&", mvpPath).replace("&Contract&", className + "Contract").replace("&Presenter&", className + "Presenter");
if (isFragment) {
String fragment = readFile("Fragment.txt").replace("&package&", packageName).replace("&mvp&", mvpPath).replace("&Fragment&", className + "Fragment").replace("&Contract&", className + "Contract").replace("&Presenter&", className + "Presenter");
writetoFile(fragment, path, className + "Fragment.java");
} else {
String activity = readFile("Activity.txt").replace("&package&", packageName).replace("&mvp&", mvpPath).replace("&Activity&", className + "Activity").replace("&Contract&", className + "Contract").replace("&Presenter&", className + "Presenter");
writetoFile(activity, path, className + "Activity.java");
}
writetoFile(contract, path, className + "Contract.java");
writetoFile(presenter, path, className + "Presenter.java");
}
private String readFile(String filename) {
InputStream in = null;
in = this.getClass().getResourceAsStream("code/" + filename);
String content = "";
try {
content = new String(readStream(in));
} catch (Exception e) {
}
return content;
}
private void writetoFile(String content, String filepath, String filename) {
try {
File floder = new File(filepath);
// if file doesnt exists, then create it
if (!floder.exists()) {
floder.mkdirs();
}
File file = new File(filepath + "/" + filename);
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] readStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
try {
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
System.out.println(new String(buffer));
}
} catch (IOException e) {
} finally {
outSteam.close();
inStream.close();
}
return outSteam.toByteArray();
}
}
使用到的工具类:
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.LinkedList;
/**
* Description: 文件工具类
* Author: djs
* Date: 2019/5/28.
*/
public class FileUtil {
public static String traverseFolder(String path) {
File file = new File(path);
if (file.exists()) {
LinkedList<File> list = new LinkedList<File>();
File[] files = file.listFiles();
String file21 = getString(list, files);
if (file21 != null) return file21;
File temp_file;
while (!list.isEmpty()) {
temp_file = list.removeFirst();
files = temp_file.listFiles();
String file2 = getString(list, files);
if (file2 != null) return file2;
}
} else {
System.out.println("文件不存在!");
}
System.out.println("没有发现文件");
return "";
}
@Nullable
private static String getString(LinkedList<File> list, File[] files) {
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夹:" + file2.getAbsolutePath());
if (file2.getName().endsWith("mvp")){
return file2.getAbsolutePath();
}
list.add(file2);
}
}
return null;
}
}
其中使用到的MVP模板就不在这里贴出了,文末会给出链接。
点击完会在目录下生成一个jar包,这个jar包,就是我们所开发的插件。
上传网址:https://plugins.jetbrains.com/
登录后点击UpLoad plugin。
idea-version版本过高导致生成jar包失败,解决办法,调低idea-version,我的调到145.0,没有问题了。
需要在 resources 目录下建 icons 文件夹,并放入2张图片,icon.png 和 icon_dark.png, 其中 icon_dark.png 是在用户选择dark主题时自动调用的。icon的大小不宜选择过大,使用16*16的就可以了。
这款插件可能因为类名或者包名的不同,并非在全部项目中适用,只需要适当修改base类就可以了。
感兴趣的朋友可以移步github:https://github.com/CnRiven/MVPPlug。
若本文帮助到了你,请不吝给个star。
感谢
https://blog.csdn.net/super_spy/article/details/80018210
https://github.com/yugai/MVPPlugin