前文《天貓客戶端元件動態化的方案——VirtualView 上手體驗》都提到了自定義模板編譯成二進位制資料的過程,在 Android 版的 Playground 裡內建了一個編譯工具可以實時調測,然而業務開發過程中,不可能在手機上編譯,而是在電腦或者後臺去編譯模板。因此這裡提供了一個獨立的工具來編譯模板,這裡介紹下它的使用方法。
相關開源庫
Android
iOS
前世今生
工具的原始碼也提交在 github 上。在一開始的設計裡,編譯模組是針對控制元件來設計的,每一個控制元件如 NText
、NImage
、VHLayout
等都有自己的編譯類,編譯類的繼承結構體系與控制元件本身的繼承結構體系一樣。它們各自會解析對應控制元件的屬性及控制元件本身的型別,將其轉換成整型值或索引序列化到最終輸出檔案裡;這就帶來了一個問題,當需要擴充套件控制元件屬性,或者新增自定義控制元件的時候,需要編寫一個新的編譯類註冊到編譯工具裡,這對開發者來說十分不友好,且不說還得搭建編譯工具工程的本身的執行環境,還得熟悉編譯器類的編寫邏輯才行。從下圖的原始設計圖就可以看出其複雜性。
為了解決這一弊端,對原始設計進行了重構,重構的核心目標就是不依賴原始碼就能進行模板編譯,思路是通過配置化的方式宣告描述控制元件型別、屬性型別、解析方式等,方案實施上是將原先針對控制元件編寫編譯類的模式改成針對屬性來編譯寫編譯類,只需要一個通用的屬性編譯類即可,具體行為都通過配置檔案來描述。將重構後的工具模板匯出可執行檔案,就可以在專案中直接使用了。廢話了這麼多,接下來就是本文的重點了。
使用說明
獨立執行模式
檔案介紹
下載原始碼之後,可執行工具存放在目錄 TemplateWorkSpace 裡,包含以下幾個檔案/目錄(或執行後產生):
檔案 | 作用 |
---|---|
config.properties | 配置元件 ID、xml 屬性對應的 value 型別 |
templatelist.properties | 編譯的模板檔案列表 |
build | 二進位制檔案的輸出目錄 |
template | xml 的存放路徑 |
compiler.jar | java 程式碼編譯後 jar 檔案,執行 xml 的編譯邏輯 |
buildTemplate.sh | 編譯執行檔案 |
如何執行
- 開啟命令列 執行
sh buildTemplate.sh
- 模板編譯後的檔案會輸出到 build 路徑下
配置 config.properties
VIEW_ID_XXXX
- 配置 xml 節點 id
- 如配置
VIEW_ID_FrameLayout=1
,則 xml 節點中的<FrameLayout>
在編譯後會用數值1代替 - 節點配置以
VIEW_ID_
開頭
property=ValueType
- 配置屬性值的型別,配置對所有模板生效,不支援在 1.xml 和 2.xml 中對相同的屬性用不同的 ValueType 解析
- 目前已經支援
- 常規型別:
String
(預設,不需要配置)、Float
、Color
、Expr
、Number
、Int
、Bool
- 特殊型別
Flag
、Type
、Align
、LayoutWidthHeight
、TextStyle
、DataMode
、Visibility
- 列舉型別
Enum<name:value,……>
- 列舉說明:
- 如配置
flexDirection=Enum<row:0,row-reverse:1,column:2,column-reverse:3>
- 在解析屬性是配置
row
直接轉化成int:0
,row-reverse
轉成int:1
- 如配置
- 列舉說明:
- 常規型別:
DEFAULT_PROPERTY_XXXX
- 為了相容就模板的編譯,寫的強制在二進位制中寫入一些屬性型別定義,可以忽略
配置 templatelist.properties
- 格式
xmlFileName=outFileName,Version[,platform]
xmlFileName
標識 template 目錄下需要編譯的 xml 檔名建議不帶.xml
字尾,目前做了相容outFileName
輸出到 build 目錄下的.out
檔名Version
表示 xml 編譯後的版本號platform
同時相容 iOS 和 android 時不寫,可填的值為android
和iphone
xml 檔案模板編寫
- 和以前的方式一樣,不需要額外寫 Java 程式碼,只需要對新增的屬性在config.properties 中配置 ValueType
介面模式
除了直接使用命令列執行工具,還可以基於此搭建完整成熟的模板工具,它可以是個客戶端,也可以是個後端服務,或者是個外掛,所以需要提供介面模式供宿主程式呼叫。
//初始化構建物件
ViewCompilerApi viewCompiler = new ViewCompilerApi();
//設定配置檔案載入器
viewCompiler.setConfigLoader(new LocalConfigLoader());
//讀取模板資料
FileInputStream fis = new FileInputStream(rootDir);
//呼叫介面,傳入必備引數,此時不區分平臺,如果要區分平臺,使用方單獨編譯即可
byte[] result = viewCompiler.compile(fis, "icon", 13);
複製程式碼