在前面介紹了Tangram框架的歷史由來(lái)和基本概念后,說(shuō)明了Tangram解決了什么問(wèn)題,可以用來(lái)做什么,核心是按照業(yè)務(wù)組件化粒度來(lái)實(shí)現(xiàn)動(dòng)態(tài)流式頁(yè)面。在此基礎(chǔ)上本文著重分析iOS上Tangram框架如何使用json數(shù)據(jù)來(lái)動(dòng)態(tài)生成流式頁(yè)面。
Tangram如何用json描述頁(yè)面
??首先要通過(guò)json數(shù)據(jù)生成視圖,我們得明白用怎么樣的格式來(lái)描述一個(gè)頁(yè)面。
??無(wú)論是iOS或是Android UI是跟用戶直接交互的重要部分,為了描述一個(gè)頁(yè)面iOS和Android都有各自的一套解決方案和實(shí)現(xiàn)思路。平常native開發(fā)的更多的是一個(gè)2D的界面,為了描述這個(gè)界面,iOS和Android都抽象了一個(gè)View的概念,一個(gè)界面是由多個(gè)View組成的,View是頁(yè)面的最小顯示單位,而整個(gè)界面是從一個(gè)根View節(jié)點(diǎn)出發(fā)的,也就是一個(gè)頁(yè)面就是一棵View組成的樹。
??最后這棵View樹如何顯示到屏幕上,這涉及到如何在平面坐標(biāo)系上放置每個(gè)View,合成位圖傳到GPU,GPU上傳到幀緩存,最后顯示到屏幕上。
??iOS上是View都有一個(gè)Frame,平面坐標(biāo)系的x坐標(biāo)、y坐標(biāo)、寬和高,既每個(gè)View知道自己在父View的位置和寬高,而屏幕左上角為(0,0)坐標(biāo)。這樣最后通過(guò)計(jì)算可以知道每個(gè)View在屏幕的位置和大小,其中還有一個(gè)z坐標(biāo)的概念,產(chǎn)生重疊知道哪個(gè)View在上,哪個(gè)在下。iOS上面是根據(jù)View的層級(jí),默認(rèn)從下往上的。隨著iOS設(shè)備屏幕類型的增多,蘋果也引入了AutoLayout,通過(guò)添加視圖之間的關(guān)系約束,最后確定View的位置。

??Android上面因?yàn)槠聊凰槠瘑?wèn)題,使用的是layout+View的方式來(lái)布局,抽象出一個(gè)布局容器的類,通過(guò)布局容器類型,綜合屏幕寬高、分辨率和View的約束最終確定每個(gè)View的位置。這樣在不同屏幕上能有一致的顯示效果。
??Tangram要保證一套Json格式在多端的同一性,如果采用iOS的布局,Json會(huì)非常復(fù)雜,而且在Android上沒辦法適配,因此最后選擇借鑒Android上的布局方案,使用布局+組件的形式來(lái)描述頁(yè)面。
??最后頁(yè)面描述如下圖:

??最后頁(yè)面由布局和組件組成的樹形結(jié)構(gòu)組成,組件其實(shí)就是一個(gè)業(yè)務(wù)組成的View,通過(guò)type映射成native的業(yè)務(wù)視圖。
??其中組件又由三部分組成,樣式、業(yè)務(wù)數(shù)據(jù)和交互,布局也有樣式。首先根據(jù)樣式,參照Anroid抽象出style通用格式,包含margin、padding、width、height等,并支持?jǐn)U展。Element的業(yè)務(wù)數(shù)據(jù)完全跟業(yè)務(wù)相關(guān),由native和業(yè)務(wù)方約定,事件則抽離出來(lái)了EventBus。
??Tangram參照Android的布局,使用Layout+Element+Event靈活一個(gè)頁(yè)面,其中Layout、Element和Event通過(guò)type和端上做一一映射。
{
"type": "container-threeColumn",
"id": "173",
"style": {
"margin": [
"20",
"30",
"20",
"30"
]
},
"items": [
{
"type": "TmallComponent2",
"imgUrl": "https://gw.alicdn.com/tps/TB1Nin9JFXXXXbXaXXXXXXXXXXX-224-224.png",
"title": "榜單"
},
{
"type": "TmallComponent2",
"imgUrl": "https://gw.alicdn.com/tps/TB1Nin9JFXXXXbXaXXXXXXXXXXX-224-224.png",
"title": "最新"
},
{
"type": "TmallComponent2",
"imgUrl": "https://gw.alicdn.com/tps/TB1Nin9JFXXXXbXaXXXXXXXXXXX-224-224.png",
"title": "歌手"
}
]
}
Tangram整體框架和各模塊功能
??明白Tangram的json格式規(guī)范后,接下來(lái)就是native如何解析數(shù)據(jù)和生成視圖了,在此之前,我們應(yīng)該先從整體上把握這個(gè)框架的結(jié)構(gòu)。最好的方式是先從模塊劃分、數(shù)據(jù)處理時(shí)序圖、架構(gòu)類圖上面分析,避免一開始就深入某一個(gè)細(xì)節(jié)。
??框架目錄如下:

- Core:TangramView視圖,自定義的類似TableView的視圖,最外層容器
- EventBus:事件處理模塊
- Factory:布局工廠、數(shù)據(jù)模型工廠、組件工廠,通過(guò)注冊(cè)機(jī)制來(lái)創(chuàng)建對(duì)應(yīng)類型的布局、模型和組件
- Helper:數(shù)據(jù)解析管理器和生成管理器,用來(lái)管理工廠和解析
- Model:通用組件數(shù)據(jù)模型
- Protocols:面向抽象接口編程,定義了工廠需要遵循的接口,布局、組件、數(shù)據(jù)模型需要遵循的協(xié)議,全部使用接口來(lái)定義,非常靈活
??解析生成框架類圖:

??其中TangramDefaultDataSourceHelper類用來(lái)封裝TangramDefaultLayoutFactory、TangramDefaultItemModelFactory、TangramDefaultElementFactory三個(gè)工廠,提供數(shù)據(jù)解析成Layout、ItemModel、Element,而這四個(gè)類遵循設(shè)計(jì)模式的開閉原則,都是用注冊(cè)的方式,方便外接擴(kuò)展,但是不建議修改。
??TangramLayoutParseHelper類是專門用來(lái)解析layout數(shù)據(jù)的,這個(gè)類沒有使用注冊(cè)的方式來(lái)解耦合,是因?yàn)椴煌膌ayout之前有很多相似的邏輯,而且layout數(shù)據(jù)格式比較統(tǒng)一。
??TangramView類圖:

Tangram如何解析生成Layout和Element
??通過(guò)上面的類圖和機(jī)構(gòu)圖,說(shuō)明了Tangram解析和生成這塊用到的類,其中定義了很多接口,面向接口編程,同時(shí)使用工廠設(shè)計(jì)模式對(duì)修改關(guān)閉對(duì)擴(kuò)展開放。
??數(shù)據(jù)處理流程圖:

執(zhí)行詳細(xì)流程圖:

- 將json數(shù)據(jù)轉(zhuǎn)為iOS系統(tǒng)的Array和Dictionary,使用TangramDefaultDataSourceHelper對(duì)數(shù)據(jù)進(jìn)行解析
- TangramDefaultDataSourceHelper中調(diào)用注冊(cè)的TangramDefaultLayoutFactory根據(jù)不同的類型將數(shù)據(jù)解析成不同的layout對(duì)象,同時(shí)調(diào)用TangramLayoutParseHelper解析類進(jìn)一步解析數(shù)據(jù),并填充數(shù)據(jù)到layout對(duì)象上
- 解析完layout后,調(diào)用注冊(cè)的Item工廠TangramDefaultItemModelFactory解析ItemModel數(shù)據(jù),ItemModel是Element的一個(gè)暫存數(shù)據(jù)對(duì)象
- ItemModel是定義的一個(gè)通用組件類,里面包含基礎(chǔ)的屬性,例如margin、height、width等,同時(shí)提供兩個(gè)map來(lái)存儲(chǔ)額外的樣式數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù),以此來(lái)支持?jǐn)U展
- 在TangramView調(diào)用代理方法,通知要顯示相應(yīng)位置的組件時(shí),再次使用TangramDefaultDataSourceHelper,調(diào)用里面注冊(cè)的TangramDefaultElementFactory工廠,根據(jù)ItemModel生成相應(yīng)的組件視圖,并填充相應(yīng)的數(shù)據(jù),同時(shí)將擴(kuò)展的屬性通過(guò)KVC映射到相應(yīng)的組件上。
??通過(guò)上面的一整套流程和框架,最終將json數(shù)據(jù)轉(zhuǎn)換成頁(yè)面顯示到屏幕上。