目录
Intellij 插件开发-AndroidStudio (零)番外
Intellij 插件开发-AndroidStudio(一)--环境构建
Intellij 插件开发-AndroidStudio(二)-文件操作
Intellij 插件开发-AndroidStudio(三)-写入生成代码
Intellij 插件开发-AndroidStudio(四)-添加类和模板
前言:
上章节中已经讲了如何从layout获取操作对象。那么接下来就是如何将我们需要的代码写入到目标文件中了。
一 写入原理
java类中,在intellij编辑器里,其实就是被他自己拆分成了不同类型的对象,如 class,method,field等。往java类里面添加代码,无非也就是添加这些东西。
关键字:PsiElementFactory、PsiClass、PsiStatement、PsiElement
PsiElementFactory 用于创建我们需要添加到java类,或者方法中的对象,不管我们要添加什么,都是需要通过他来构建一个待添加的对象
PsiClass 很好理解,就是操作类,这个可以是当前操作的类,也可以是内部类,甚至别的类。
PsiStatement 代码块对象,通常无语法限制。说白了就是插入一段任意代码
PsiElement 代码对象,通常有语法限制,如field对象,method对象等。
二 示例代码
写入代码
public static void loadFile(@NotNull Project project, Editor editor, PsiFile currentFile) throws IncorrectOperationException {
DocumentUtil.writeInRunUndoTransparentAction(new Runnable() {
@Override
public void run() {
String layoutName = editor.getSelectionModel().getSelectedText();
PsiFile xmlFile = AndroidUtils.findXmlResource(project, layoutName);
if (xmlFile == null) {
return;
}
//获取到layout中的view对象
List<AndroidView> androidViews = AndroidUtils.getIDsFromXML(xmlFile);
int offset = editor.getCaretModel().getOffset();
//获取到正在编辑器中编辑的方法体。
PsiElement psiElement = currentFile.findElementAt(offset);
PsiStatement psiStatement = PsiTreeUtil.getParentOfType(psiElement, PsiStatement.class);
//获取当前操作的java类
PsiClass psiClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass.class);
//获取原来的成变量
Set<String> fieldSet = new HashSet<String>();
for (PsiField field : psiClass.getFields()) {
fieldSet.add(field.getName());
}
final Set<String> thisSet = new HashSet<String>();
processElement(psiElement, thisSet);
//获取当前工程的操作factory,要靠这个对象来进行添加对象的创建
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
//导入android.view包
JavaCommonUtils.importAndroidPackage(psiClass, project, "View");
String clickStr = "private View.OnClickListener mOnClickListener = new View.OnClickListener() {" +
" @Override\n" +
" public void onClick(View v) {\n" +
" switch (v.getId()) {\n" +
" ";
//遍历每个操作view,生成对应需要的代码。内部拼装方式,很好懂
for (AndroidView v : androidViews) {
if (!fieldSet.contains(v.getFieldName())) {
String sb = "private " + v.getName() + " " + v.getFieldName() + ";";
psiClass.add(elementFactory.createFieldFromText(sb, psiClass));
JavaCommonUtils.importAndroidPackage(psiClass, project, v.getName());
}
if (!thisSet.contains(v.getFieldName())) {
clickStr = clickStr + "case " + v.getId() + ":\n\nbreak;";
String sb1;
sb1 = String.format("%s = (%s) findViewById(%s);", v.getFieldName(), v.getName(), v.getId());
PsiStatement statementFromText = elementFactory.createStatementFromText(sb1, null);
psiStatement.getParent().addAfter(statementFromText, psiStatement);
String sb2;
sb2 = String.format("%s.setOnClickListener(%s);", v.getFieldName(), "mOnClickListener");
PsiStatement clickStrStatement = elementFactory.createStatementFromText(sb2, null);
psiStatement.getParent().addAfter(clickStrStatement, psiStatement);
}
}
clickStr = clickStr + "default:\n" +
" break;\n" +
" }\n" +
" }\n" +
" };";
System.out.print(clickStr);
//把拼装好的点击事件的对象添加到类中。
PsiStatement clickText = elementFactory.createStatementFromText(clickStr, null);
psiStatement.getParent().addAfter(clickText, psiElement);
//CodeStyle
CodeStyleManager.getInstance(project).reformat(psiClass.getParent());
}
});
}