項目源碼
https://github.com/boredream/AndroidDatabaseGeneratorPlugin
系列教程
Android Studio Plugin 插件開發教程(一) —— 開發你的第一個插件
Android Studio Plugin 插件開發教程(二) —— 插件SDK中的常用對象介紹
Android Studio Plugin 插件開發教程(三) —— 制作一個自動生成數據庫代碼的插件
Android Studio Plugin 插件開發教程(四) —— 為自動生成數據庫代碼的插件添加UI
先樹立一個概念,AS里項目的一切都可以視為對象,比如整個項目,項目里的每個文件,文件里的每個方法、每行語句等等都是一個對象。我們插件SDK的開發,主要工作就是針對這一個個的對象的分析和處理
下面開始介紹幾個主要的對象類
Virtual File
虛擬文件類。
可以當做Java開發中的File對象理解,概念比較類似
獲取方法
- 通過Action獲取: event.getData(PlatformDataKeys.VIRTUAL_FILE).
這個也是之前教程(一)中的獲取方法 - 通過本地文件路徑獲取: LocalFileSystem.getInstance().findFileByIoFile()
- 通過PSI file獲取: psiFile.getVirtualFile()
- 通過document獲取: FileDocumentManager.getInstance().getFile()
用處
傳統的文件操作方法這個對象都支持,比如獲取文件內容,重命名,移動,刪除等
PSI File
PSI系統下的文件類。
獲取方法
- 通過Action獲取: e.getData(LangDataKeys.PSI_FILE).
- 通過VirtualFile獲取: PsiManager.getInstance(project).findFile()
- 通過document獲取: PsiDocumentManager.getInstance(project).getPsiFile()
- 通過文件中的Element元素獲取: psiElement.getContainingFile()
如果要通過名字獲取,請使用 FilenameIndex.getFilesByName(project, name, scope)
用處
作為PSI系統中的一個元素,可以使用PSI Element的各種具體方法
看到這里肯定很多人一臉迷惑,這倆File有啥區別?PSI是啥?Element又是啥?
什么是PSI系統?
PSI 是 Program Structure Interface 的簡寫。從名字可以看出來它是一個接口,相當于把項目中的一切都封裝了起來,比如類、方法、語句等,讓他們都成為了同一個系統內的實現。封裝的對象類都統一加了個前綴比如PsiClass、PsiMethod等。
Virtual File 和 PSI File的區別?
如果學過Dom和Parse解析就很好理解了,Virtual File就是xml文件本身的一個抽象對象。而PSI File就類似于Dom下xml文件解析成的Document對象,雖然也是“文件”,但是特殊封裝過的~ 這個PsiFile是整個PSI系統下的文件對象,和PSI下的其他Element元素相通~
PSI Element是什么?
PSI Element是PSI系統下不同類型對象的一個統稱,是基類。
比如之前提到的PsiMethod、PsiClass等等都是一個個具體的PsiElement實現。
可能還會有點迷惑,下面寫個demo幫助理解。
我們通過ActionEvent的getData方法,傳入對應KEY獲取PsiFile(Action類創建參考上篇教程),然后遍歷PsiFile文件下所有的子級元素,打印出來(日志顯示在開發插件的IDE的控制臺)
注意,這個直接獲取的PsiFile默認為當前我們當前所選的文件
@Override
public void actionPerformed(AnActionEvent e) {
PsiFile file = e.getData(PlatformDataKeys.PSI_FILE);
for (PsiElement psiElement : file.getChildren()) {
System.out.println(psiElement);
}
}
代碼run起來
運行起來的IDE我們新建一個Android Project,默認主頁面代碼如下
然后在菜單中 Code | Database Generate 調用我們編寫的插件
運行結果日志如下:
PsiPackageStatement:com.boredream.plugindemo
PsiWhiteSpace
PsiImportList
PsiWhiteSpace
PsiClass:MainActivity
PsiWhiteSpace
這里把MainActivity文件下所有的子級Element都列出來了(只遍歷直接子級)
看名字就能知道意思,PsiPackageStatement是包名語句,PsiClass是類。。。甚至還有PsiWhiteSpace,空白都專門有個類型啊!細致!
這里不同的Element還有自己對應的特殊方法,比如PsiClass就和Java中的Class類似,可以獲取Field、Method等。下面我們再簡單改造下Demo,獲取MainActivity文件中Class里面的元素。
@Override
public void actionPerformed(AnActionEvent e) {
PsiFile file = e.getData(PlatformDataKeys.PSI_FILE);
for (PsiElement psiElement : file.getChildren()) {
if(psiElement instanceof PsiClass) {
PsiClass clazz = (PsiClass) psiElement;
PsiMethod method = clazz.getMethods()[0];
System.out.println(method.getName());
System.out.println(method.getParameterList().getText());
}
}
}
同樣,再次run項目,然后調用插件
運行結果日志如下:
onCreate
(Bundle savedInstanceState)
這次我們遍歷獲取了PsiClass類對象,然后獲取它內部的第一個方法,并打印方法的名字和方法參數的文字
本篇教程結束~
下一章,我們將開擼 自動生成數據庫插件代碼的實戰~
然后一邊寫插件一邊再學習新的內容