<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          知乎移動(dòng)端動(dòng)態(tài)化探索與實(shí)踐!

          共 7842字,需瀏覽 16分鐘

           ·

          2021-10-16 09:08

          ?BATcoder技術(shù)群,讓一部分人先進(jìn)大廠

          大家,我是劉望舒,騰訊TVP,著有三本業(yè)內(nèi)知名暢銷書,連續(xù)四年蟬聯(lián)電子工業(yè)出版社年度優(yōu)秀作者,谷歌開發(fā)者社區(qū)特邀講師,百度百科收錄的高級技術(shù)專家,CSDN 2018年度博客之星。

          前華為架構(gòu)師,現(xiàn)大廠技術(shù)總監(jiān)。


          想要加入?BATcoder技術(shù)群,公號回復(fù)BAT?即可。

          作者: 于天航
          https://zhuanlan.zhihu.com/p/64968076

          2018 年初,隨著知乎商業(yè)化腳步的逐漸加快,業(yè)務(wù)上對產(chǎn)品體驗(yàn)、迭代速度、效果驗(yàn)證等方面的優(yōu)化訴求越來越強(qiáng)烈,移動(dòng)端需求的用戶觸達(dá)效率成為大家關(guān)注的焦點(diǎn)問題。因此,商業(yè)化移動(dòng)端團(tuán)隊(duì)在制定 OKR 時(shí)確立了「賦能」和「提效」兩大目標(biāo),旨在解決三個(gè)業(yè)務(wù)痛點(diǎn):
          1. 移動(dòng)端需求的用戶觸達(dá)效率低,新的產(chǎn)品樣式上線不夠快。想要快速上線新樣式有兩個(gè)思路:要么縮短現(xiàn)有客戶端發(fā)版周期;要么通過云端下發(fā)的方式實(shí)現(xiàn)樣式的動(dòng)態(tài)更新。知乎 App 在發(fā)版周期上已經(jīng)做了大量嘗試,但由于 App 端版本發(fā)布方式的天然限制,在某些業(yè)務(wù)場景下無法很好的滿足要求;

          2. 廣告樣式實(shí)驗(yàn)粒度粗放,實(shí)驗(yàn)相關(guān)代碼管理復(fù)雜。這一痛點(diǎn)可以看作是痛點(diǎn)一的延續(xù)。AB 實(shí)驗(yàn)是產(chǎn)品效果提升的重要手段,為了支持實(shí)驗(yàn),要在 App 發(fā)版時(shí)預(yù)埋多套代碼,進(jìn)行復(fù)雜的實(shí)驗(yàn)開關(guān)及樣式代碼管理,同時(shí)還要考慮實(shí)驗(yàn)下線邏輯。如果實(shí)驗(yàn)粒度很細(xì),邏輯維護(hù)成本會(huì)指數(shù)增加;

          3. 廣告落地頁(Landing Page)的性能和轉(zhuǎn)化效果亟待提升。非原生廣告落地頁多為非知乎域的 H5 落地頁,App 端對其控制能力極其有限,在對 H5 類型落地頁本身進(jìn)行優(yōu)化的同時(shí),也希望探索新的方向。(第三方 H5 落地頁的打開速度和數(shù)據(jù)采集,可以采用「CDN 加速」、「XPath」等方案優(yōu)化,這兩個(gè)不是本文的重點(diǎn),在這里就不展開討論了。)

          基于此商業(yè)移動(dòng)端團(tuán)隊(duì)開始著手搭建移動(dòng)端動(dòng)態(tài)化基礎(chǔ)能力,并一步步實(shí)現(xiàn)了 App 內(nèi)各個(gè)位置廣告卡片的動(dòng)態(tài)化開發(fā)和上線,我們給這個(gè)方案起了個(gè)比較「動(dòng)態(tài)」的名字叫 Morph。


          下面從「技術(shù)選型」、「架構(gòu)設(shè)計(jì)」、「動(dòng)態(tài)化基礎(chǔ)能力建設(shè)」三個(gè)方面介紹一下此次的技術(shù)方案改造升級。


          1. 進(jìn)行了哪些技術(shù)選型?

          在方案設(shè)計(jì)之初,我們就確立了實(shí)現(xiàn)商業(yè)廣告全面動(dòng)態(tài)化的技術(shù)愿景,覆蓋從信息流廣告卡片到廣告主落地頁的所有功能場景。近些年,移動(dòng)端動(dòng)態(tài)化方案可謂百花齊放,如何選擇一個(gè)適合知乎商業(yè)化業(yè)務(wù)場景的動(dòng)態(tài)化方案成為我們第一個(gè)要解決的問題。

          1.1 為什么是 DSL Native+?

          從「支持動(dòng)態(tài)化的程度」、「與原生體驗(yàn)的差異」、「方案集成與功能開發(fā)成本的高低」三個(gè)維度出發(fā),將市面上的移動(dòng)端動(dòng)態(tài)化方案分成三個(gè)方向:

          新的動(dòng)態(tài)化方案需要滿足「跨平臺(tái)」、「熱更新」兩個(gè)基本訴求,因此沒有考慮 Android 插件化這個(gè)大類下的方案。

          • Web 增強(qiáng)(Web+) : 主要基于 WebView 實(shí)現(xiàn),能夠進(jìn)行快速的迭代,在知乎已經(jīng)有了對應(yīng)的解決方案;GPL 和 DSL 可以看作「Native 增強(qiáng)(Native+)」方向的子方向,Native+ 方向基于 App 內(nèi)自帶的語言解析器,獨(dú)立于 WebView 實(shí)現(xiàn)動(dòng)態(tài)化邏輯的解析、布局和渲染。

          • 基于 GPL 的 Native 增強(qiáng)(GPL) : 這個(gè)方向是移動(dòng)端動(dòng)態(tài)化的熱門方向,React Native、Flutter、NativeScript 等等,實(shí)現(xiàn)原理各不相同,共同的特點(diǎn)是利用了通用編程語言器,可以是系統(tǒng)提供的(如 Javascript),或者是集成到 App 的(如 Dart),再輔以某個(gè)布局系統(tǒng)和渲染方案,由于語言是圖靈完備的,可以提供完美的動(dòng)態(tài)化解決方案;

          • 基于 DSL 的 Native 增強(qiáng)(DSL): GPL 方案雖然美好但始終需要在動(dòng)態(tài)化能力、渲染性能、Framework 體積、學(xué)習(xí)和開發(fā)成本等方面取舍,難以達(dá)到完美。于是產(chǎn)生了基于領(lǐng)域?qū)S谜Z言的解決方案,此類方案通過采用適合專業(yè)場景的的 DSL 解析云端下發(fā)的邏輯結(jié)構(gòu),舍棄一部分動(dòng)態(tài)化靈活性,換取其他方面的優(yōu)勢。

          動(dòng)態(tài)化方案選擇要考量的因素很多,如渲染效率、動(dòng)態(tài)化靈活程度與用戶體驗(yàn)的取舍、方案實(shí)現(xiàn)成本等等。其中重點(diǎn)強(qiáng)調(diào)一下「方案實(shí)現(xiàn)成本」,這個(gè)因素應(yīng)該基于開發(fā)團(tuán)隊(duì)的現(xiàn)狀進(jìn)行考量,可以包括開發(fā)成本、學(xué)習(xí)成本和人才培養(yǎng)成本,開發(fā)成本很好理解,即該方案從調(diào)研到落地的工作成本;學(xué)習(xí)成本和人才培養(yǎng)成本往往是我們?nèi)菀缀雎缘模趫F(tuán)隊(duì)已經(jīng)掌握的技術(shù)棧,不同的方案需要的需要掌握的知識有所不同,學(xué)習(xí)成本也不同。而人才培養(yǎng)成本強(qiáng)調(diào)的是市場上是否有對應(yīng)的專業(yè)人才,不是很熟悉或者沒有親身實(shí)踐過這個(gè)技術(shù)方案的人多久能夠熟練掌握這項(xiàng)技能?比如 RN 為代表的基于 Javascript 的 GPL 方案通常需要前端開發(fā)技能和移動(dòng)端開發(fā)技能的配合使用,對人力培養(yǎng)成本比 Native+ 和 Web + 的成本要高。

          討論了這么多,我們應(yīng)該選哪個(gè)方向呢?針對公司現(xiàn)有的業(yè)務(wù)場景、工程現(xiàn)狀,我們梳理出需要優(yōu)先考量的原則:

          • 接近 Native 的高性能: 廣告動(dòng)態(tài)化的核心要求。相比于 Web 的靈活性,接近 Native 性能需求更強(qiáng)烈。滑動(dòng)流暢是信息流產(chǎn)品的基礎(chǔ)需求,而對于落地頁,打開速度和使用體驗(yàn)也是重中之重;
          • 項(xiàng)目能夠快速啟動(dòng): 高速發(fā)展的業(yè)務(wù)訴求。項(xiàng)目需要能夠快速啟動(dòng),快速上線,本文所講的動(dòng)態(tài)化方案僅每端投入一人月就完成了第一個(gè)版本的上線;
          • 低人力成本 : 在業(yè)務(wù)快速迭代的過程中,支撐業(yè)務(wù)開發(fā)的同時(shí),技術(shù)方案上的投入資源有限,前后端都很難有充足的人力投入,新方案應(yīng)該占用盡可能少的人力,并且對現(xiàn)有工程的改造降至最低;
          • App 包體積影響小: 知乎 App 重視用戶體驗(yàn),新技術(shù)對 App 性能、包體積不能產(chǎn)生負(fù)面影響。包體積是影響應(yīng)用增長的重要因素,App Store 應(yīng)用如果超過 150M,則無法在 4G 環(huán)境下下載,將會(huì)極大的影響 App 的增長,所以新的方案需要盡可能少的影響包體積;
          • 平滑遷移: 基于技術(shù)架構(gòu)現(xiàn)狀。商業(yè)廣告卡片是基于信息流的,不能因?yàn)閺V告動(dòng)態(tài)化而要求整個(gè)信息流重構(gòu),所以需要保證新的方案能夠和現(xiàn)有信息流方案完全兼容;
          • 持續(xù)演進(jìn): 快速啟動(dòng)后的發(fā)展方案。整體框架需要支持高擴(kuò)展性,可以在上線后進(jìn)行持續(xù)的需求迭代。

          「Web+」方向在性能和穩(wěn)定性上略差,而且使用場景有限,不適合在信息流這種流暢性要求高的場景中使用;「GPL」方向提供一套完全不同于 Native 的開發(fā)模式,可以在其基礎(chǔ)上實(shí)現(xiàn)動(dòng)態(tài)化功能,且能夠保證較好的性能,但是目前的解決方案接入成本和學(xué)習(xí)成本都比較高,并且與復(fù)雜業(yè)務(wù)場景結(jié)合時(shí)均有難以解決的問題,不適合在已有業(yè)務(wù)中接入。

          綜上考慮,最終我們決定采用基于 Flexbox 的 DSL Native+ 動(dòng)態(tài)化方案即 Morph。Morph 方案在業(yè)務(wù)上具有如下優(yōu)勢:

          • 和現(xiàn)有技術(shù)棧完美融合。知乎 App 信息流基于 ComponentKit 實(shí)現(xiàn)的,幾乎幾乎不會(huì)產(chǎn)生額外的學(xué)習(xí)成本;
          • 快速上線,后期維護(hù)成本較低:整體方案的上手難度低,不需要學(xué)習(xí)新的技術(shù),能夠快速進(jìn)行功能迭代開發(fā);
          • 對包體積影響小:整個(gè)方案只是增加了 Google-FlexboxLayout、Yoga 兩個(gè)輕量級開源布局框架,對體積影響可以忽略不計(jì);
          • 這個(gè)方案還帶來了一個(gè)額外的好處:支持現(xiàn)有實(shí)驗(yàn)系統(tǒng),很好的滿足樣式實(shí)驗(yàn)、數(shù)據(jù)采集的需求。

          1.2 為什么是 Flexbox?

          動(dòng)態(tài)布局方案基于 Flexbox,帶來的好處是:

          • Flexbox 為盒狀模型提供最大的靈活性,是目前布局系統(tǒng)的首選;
          • 跨平臺(tái)方案,雙端統(tǒng)一;
          • 和知乎 App 現(xiàn)有技術(shù)棧匹配度高,開源環(huán)境中有優(yōu)秀開源庫的本地化。
          • iOS 端 Facebook 開源的 Yoga 已經(jīng)經(jīng)過 10+ release 迭代,有 1.1w+ 的 Star,(ComponentKit 底層也是依賴于 Yoga),在生產(chǎn)環(huán)境經(jīng)過長時(shí)間驗(yàn)證;
          • Android 端的 Yoga 庫有一些難以解決的問題,最終選擇 Google 的 FlexboxLayout 框架來解析,該框架也非常成熟,在和 iOS Yoga 配合中僅需要很少的雙端適配。

          1.3 為什么是 JSON?

          布局描述語言上,由于各種描述語言的描述能力差異不大,在這種情況下,開發(fā)成本成為我們選型描述語言的重點(diǎn)。

          開發(fā)成本考慮的是基于知乎 App 現(xiàn)有客戶端和后端的交互結(jié)構(gòu),目前前后端數(shù)據(jù)傳輸采用的是 JSON 格式,如果要換成其他格式的數(shù)據(jù),客戶端和后端都需要進(jìn)行額外的工作處理,最終我們選擇了 JSON 格式來描述布局樣式。


          2. Morph 動(dòng)態(tài)化方案架構(gòu)如何設(shè)計(jì)?

          我們將一個(gè)使用 Morph DSL 系統(tǒng),以 JSON 格式組織的描述一個(gè)視圖樹結(jié)構(gòu)的配置稱為樣式。實(shí)現(xiàn)動(dòng)態(tài)化的核心業(yè)務(wù)流程是實(shí)現(xiàn)布局文件云端下發(fā)和解析:編寫樣式文件 -> 上傳到服務(wù)端 -> 云端下發(fā)樣式到 App 端 -> App 端收到廣告數(shù)據(jù)后解析樣式文件展示廣告。

          商業(yè)廣告業(yè)務(wù)數(shù)據(jù)存放在業(yè)務(wù)后端,和 App 端直接交互的是引擎后端,所以整個(gè)系統(tǒng)中涉及到三個(gè)端的調(diào)整。業(yè)務(wù)端相當(dāng)于商業(yè)廣告數(shù)據(jù)的生產(chǎn)者,業(yè)務(wù)端分業(yè)務(wù)前端和業(yè)務(wù)后端,業(yè)務(wù)前端提供面向廣告主投放廣告的平臺(tái)(投放平臺(tái)、建站工具),業(yè)務(wù)后端負(fù)責(zé)存儲(chǔ)和處理廣告相關(guān)的數(shù)據(jù)(廣告模版、廣告訂單、排期等)。廣告引擎則是從業(yè)務(wù)端獲取廣告數(shù)據(jù)進(jìn)行過濾和篩選,最后選取符合規(guī)則的廣告下發(fā)給 App 端,同時(shí)引擎端實(shí)驗(yàn)平臺(tái)負(fù)責(zé)對 App 端流量進(jìn)行分流。

          結(jié)合現(xiàn)有業(yè)務(wù)場景,Morph 系統(tǒng)結(jié)構(gòu)設(shè)計(jì)如下圖所示:

          • 廣告請求接口 :以信息流為例,用戶刷新信息流展現(xiàn)廣告卡片,引擎端從業(yè)務(wù)后端廣告數(shù)據(jù)庫中讀取廣告數(shù)據(jù)下發(fā)給 App 端,廣告數(shù)據(jù)中包含了對應(yīng)廣告卡片的樣式名稱。
          • 樣式下發(fā)接口 : 樣式文件較多,因此與數(shù)據(jù)接口分開,通過獨(dú)立的樣式服務(wù)接口進(jìn)行下發(fā)。

          隨著產(chǎn)品的演進(jìn),動(dòng)態(tài)化樣式數(shù)量持續(xù)增加,為保證研發(fā)效率的規(guī)避風(fēng)險(xiǎn),上線了「樣式管理平臺(tái)」,提供可視化界面進(jìn)行樣式的增刪改查等工作。

          Morph 的業(yè)務(wù)數(shù)據(jù)流向如下圖所示:

          1. 針對產(chǎn)品提出樣式需求,由 App 端和業(yè)務(wù)端協(xié)商出新的廣告模版和樣式映射關(guān)系,客戶端通過樣式管理平臺(tái)提交新的樣式,存儲(chǔ)到云端樣式數(shù)據(jù)庫,業(yè)務(wù)端將模版和樣式名稱映射存入廣告數(shù)據(jù)庫;

          2. App 啟動(dòng)時(shí),訪問樣式服務(wù)接口,樣式服務(wù)根據(jù)請求 Header 中的:App 平臺(tái)、App 版本,以及 App 端現(xiàn)有基礎(chǔ)樣式及版本信息集合,增量下發(fā)廣告樣式數(shù)據(jù)。App 接收到新的廣告樣式數(shù)據(jù)后,會(huì)依次進(jìn)行:Hash 校驗(yàn)、JSON 格式校驗(yàn)、實(shí)驗(yàn)信息的校驗(yàn),校驗(yàn)通過后將接收到新的樣式文件更新到本地樣式數(shù)據(jù)庫,同時(shí)進(jìn)行對舊版本樣式數(shù)據(jù)進(jìn)行清理刪除;

          3. App 端信息流刷新,向引擎請求帶有樣式名稱及實(shí)驗(yàn)信息的廣告數(shù)據(jù),App 端根據(jù)數(shù)據(jù)中的樣式名稱選擇對應(yīng)的樣式文件生成布局,展示廣告卡片。


          3. 動(dòng)態(tài)化能力建設(shè)中最核心的4個(gè)部分

          這個(gè)部分和大家探討 Morph 動(dòng)態(tài)化基礎(chǔ)能力搭建的核心思路。

          上圖展示了動(dòng)態(tài)化能力建設(shè)中的4個(gè)核心部分,下文將逐個(gè)闡述。

          3.1 DSL 定義

          基于 DSL Native+ 的動(dòng)態(tài)化方案設(shè)計(jì)首先要解決的一個(gè)問題是 DSL 的選擇,Morph DSL 包含三個(gè)核心設(shè)計(jì)思路:

          1. 基于前端 Flexbox 布局系統(tǒng)進(jìn)行視圖布局;
          2. 使用 JSON 數(shù)據(jù)交互語言描述視圖結(jié)構(gòu);
          3. JSON 節(jié)點(diǎn)使用屬性「type」區(qū)分視圖控件類型。

          下圖是 Morph DSL 屬性集中的一個(gè)子集:

          屬性集包含六種屬性:布局屬性,視圖屬性,數(shù)據(jù)屬性,交互屬性,條件屬性,容器屬性。

          1. 布局屬性

          決定視圖樹結(jié)構(gòu),規(guī)劃視圖布局位置的相關(guān)屬性,如上圖中的FlexStyle,F(xiàn)lexStyle 中各屬性命名及含義,與 Flexbox 定義一一對應(yīng)。得益于 Flexbox 布局系統(tǒng)簡潔、強(qiáng)大的彈性布局能力,Morph DSL 幾乎可以實(shí)現(xiàn)任何形式的布局;

          2. 視圖屬性

          與視圖 UI 樣式相關(guān)的屬性,如背景色、透明度、圓角等,如 ViewStyle。基于 Flexbox 帶來的另一個(gè)好處是解決了屏幕適配的問題,而在尺寸換算問題上,我們規(guī)定:Morph DSL 布局中,使用 2 倍圖下的尺寸,單位為 px,Android 和 iOS 端解析具體的數(shù)值時(shí),將分別換算成本地的、與設(shè)備無關(guān)的 dp 或 pt 來使用;

          3. 數(shù)據(jù)屬性

          表達(dá)節(jié)點(diǎn)與數(shù)據(jù)綁定關(guān)系的屬性,在不同的視圖控件中有所區(qū)別,具體細(xì)節(jié)將在下文「數(shù)據(jù)綁定」中闡述;

          4. 交互屬性

          設(shè)置視圖節(jié)點(diǎn)的點(diǎn)擊等事件的屬性,主要由 ViewAction 指定。ViewAction 描述一個(gè)視圖節(jié)點(diǎn)的交互類型,結(jié)構(gòu)如下:

          action 指明該交互要完成的動(dòng)作,extra 攜帶交互需要的信息和數(shù)據(jù)。上圖展示的布局片段,描述了一個(gè) CLICK 事件,觸發(fā)后,將從 extra 中取出 URL 信息,并進(jìn)行跳轉(zhuǎn)。目前 Morph 已定義的通用 action 類型及規(guī)則舉例:

          5. 條件屬性

          Morph 定義了一套 condition 機(jī)制,支持在樣式文件中根據(jù)業(yè)務(wù)邏輯做條件判斷,如互動(dòng)數(shù)據(jù)的展示等。condition 定義如下:

          目前 condition 支持主要的邏輯運(yùn)算:or(邏輯或)、and(邏輯與)、not(邏輯非)、notEmpty(非空)、empty(空)、valueOf(取 bool 值)。

          以下是一個(gè)使用了 condition 的一個(gè)文本節(jié)點(diǎn)示例,其中,visibility 決定了該控件最終是否會(huì)顯示,其類型就是一個(gè) condition 類型:

          6. 容器屬性:在 Morph DSL 中規(guī)定,樣式的根節(jié)點(diǎn)必須是一個(gè) container,以下是一個(gè)根節(jié)點(diǎn)示例:

          container 對應(yīng)于 App 端支持了 Flexbox 布局系統(tǒng)的容器控件。container 使用屬性 children 來描述容器內(nèi)嵌套的子視圖,children 是一個(gè)數(shù)組,可以包含任意多個(gè)控件節(jié)點(diǎn)。通過這種方式,Morph DSL 可以描述任意結(jié)構(gòu)的視圖樹。

          下例中,使用了 height 屬性來指定控件的高度。Morph 設(shè)計(jì)之初,我們將控件的寬高定義為一個(gè)復(fù)合屬性:

          在后期技術(shù)演進(jìn)過程中,我們使用了更簡潔的字符串類型的 layoutHeight、layoutWidth 來描述高和寬:

          3.2 動(dòng)態(tài)視圖管理

          我們把前文提過的樣式文件從開發(fā)到寫入 App 端本地樣式數(shù)據(jù)庫的完整流程畫成時(shí)序圖:

          1. 基于自定義 DSL 進(jìn)行編寫樣式;
          2. 樣式文件經(jīng)由樣式管理平臺(tái)存入云端樣式數(shù)據(jù)庫:
          3. App 端請求樣式服務(wù)接口;
          4. 樣式服務(wù)接口收到請求后,根據(jù)一定的策略進(jìn)行樣式下發(fā);
          5. App 端將接收到的樣式進(jìn)行校驗(yàn)后,寫入本地樣式數(shù)據(jù)庫,以備后續(xù)使用。

          云端/本地樣式數(shù)據(jù)庫的設(shè)計(jì)如下:

          樣式下發(fā)接口的參數(shù)設(shè)計(jì)如下:

          值得注意的是:

          • App 端請求樣式下發(fā)時(shí),會(huì)帶上當(dāng)前 App 端已支持的樣式信息,樣式服務(wù)據(jù)此判斷進(jìn)行增量而非全量的樣式下發(fā),節(jié)省傳輸成本;
          • 某樣式單個(gè)平臺(tái)版本號為空時(shí),不向該平臺(tái)下發(fā)該樣式;
          • 某樣式支持的最低 App 端版本大于當(dāng)前 App 端版本時(shí),不下發(fā)該樣式。

          3.3 構(gòu)建視圖

          客戶端為每一個(gè) UI 組件創(chuàng)建專門的解析器。對于每一種樣式,使用單獨(dú)的樣式名稱 style 來標(biāo)識,樣式文件中引用的每種組件會(huì)一一對應(yīng)到字段 type 表明該樣式所使用的控件類型。因此當(dāng) App 端獲取到樣式文件后,通過樣式中每個(gè)元素的 type,由解析器決定使用哪種原生控件進(jìn)行承載。

          解析器主要承擔(dān) 2 項(xiàng)職責(zé):

          1. 根據(jù) JSON 節(jié)點(diǎn)的屬性配置創(chuàng)建一個(gè)本地對應(yīng)的控件,解析控件綁定的具體數(shù)據(jù)并設(shè)置到控件上;
          2. 通過每個(gè)節(jié)點(diǎn)中的 type 字段,將每一個(gè)節(jié)點(diǎn)交由對應(yīng)的組件解析器去解析,解析的結(jié)果是輸出一個(gè)對應(yīng)的 UI 控件。

          由于所有節(jié)點(diǎn)已按照樹形結(jié)構(gòu)存儲(chǔ),最終輸出所有 UI 控件時(shí),按照樹形結(jié)構(gòu)進(jìn)行組織,就可以生成最終的目標(biāo)視圖卡片。

          以 Android 端為例,簡要闡述視圖解析器實(shí)現(xiàn)的技術(shù)要點(diǎn):

          • 每一類型的視圖控件,都在 App 端有唯一對應(yīng)的 ViewModel(樣式文件的布局屬性 Model 化的產(chǎn)物)和 ViewParser(視圖解析器,利用 ViewModel 創(chuàng)建本地View并設(shè)置屬性)
          • ViewModel 及 ViewParser 的注冊,由自定義注解 @ViewModel("type") 及 @ViewParser("type") 完成,在編譯期將通過插件自動(dòng)收集并插入注冊代碼;
          • 構(gòu)建視圖時(shí),遍歷 model 樹,通過 model 的 type 字段,獲取已注冊的 ViewParser,反射構(gòu)造一個(gè)解析器實(shí)例,傳入 ViewModel,完成單個(gè)視圖控件的創(chuàng)建;
          • 由于使用遞歸遍歷,某個(gè)節(jié)點(diǎn)的視圖控件構(gòu)建完成后,其父節(jié)點(diǎn)必定已構(gòu)建完成,因此直接將當(dāng)前視圖控件,加入父控件即可。

          3.4 綁定數(shù)據(jù)

          樣式文件的主要功能是設(shè)置視圖顯示約束,其中包含了與視圖顯示屬性相關(guān)的設(shè)置,以及對應(yīng)顯示的內(nèi)容數(shù)據(jù)字段。因此在樣式解析后,還需要進(jìn)行顯示數(shù)據(jù)的綁定。下圖是一個(gè)圖片控件節(jié)點(diǎn)的布局示例。

          「url」為該控件的一個(gè)數(shù)據(jù)屬性,表示該圖片控件要顯示的圖片鏈接的地址,其值 ?指向了一個(gè) JSON 數(shù)據(jù)體中的一個(gè)具體節(jié)點(diǎn):

          我們規(guī)定指向數(shù)據(jù)體節(jié)點(diǎn)的引用使用 ?作為結(jié)束標(biāo)識,數(shù)組直接使用數(shù)字下標(biāo)指定其具體位置。如上面的引用 ?中,ads 指數(shù)據(jù)體中的一個(gè)數(shù)組節(jié)點(diǎn),而0標(biāo)識取數(shù)組的第一個(gè)元素,creative 表示一個(gè) JSONObject 節(jié)點(diǎn),image 表示 creative 節(jié)點(diǎn)下的一個(gè)具體字段值。

          以上文的圖片控件為例,數(shù)據(jù)綁定過程如下:

          1. 調(diào)用數(shù)據(jù)綁定接口,將數(shù)據(jù)體傳入接口;
          2. 遍歷已構(gòu)建好的視圖樹,遍歷每一個(gè)節(jié)點(diǎn)時(shí),將從該節(jié)點(diǎn)控件中取出對應(yīng)的 ViewModel 對象(視圖構(gòu)建時(shí),會(huì)作為 tag 與控件綁定),再獲取對應(yīng)的控件解析器;3.調(diào)用解析器,解析器中將使用數(shù)據(jù)引用和數(shù)據(jù)體,共同完成解析,拿到最終的數(shù)據(jù)(如圖片鏈接 url);
          3. 解析器按照控件自身具體的規(guī)則,完成數(shù)據(jù)設(shè)置。

          4. 寫在最后

          Morph 移動(dòng)端動(dòng)態(tài)化技術(shù)方案自上線以來,經(jīng)過多輪迭代,支持了大量控件并覆蓋了多數(shù)業(yè)務(wù)場景。

          雖然項(xiàng)目未開源,且文章中的一些技術(shù)可能時(shí)至今日已經(jīng)有了新的方案(文章完成于?2?年前)但是文中分享的關(guān)于技術(shù)選型的考量以及具體實(shí)現(xiàn)思路,對大家仍然具有參考意義。


          ·················END·················

          推薦閱讀

          ? 耗時(shí)2年,Android進(jìn)階三部曲第三部《Android進(jìn)階指北》出版!

          ? 『BATcoder』做了多年安卓還沒編譯過源碼?一個(gè)視頻帶你玩轉(zhuǎn)!

          ? 『BATcoder』我去!安裝Ubuntu還有坑?

          ? 重生!進(jìn)階三部曲第一部《Android進(jìn)階之光》第2版 出版!

          為了防止失聯(lián),歡迎關(guān)注我的小號


          ??微信改了推送機(jī)制,真愛請星標(biāo)本公號??
          瀏覽 97
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产熟女一区二区三区四区 | 奶大灬舒服灬一进一出三区 | 欧美激情在线 | 亚洲二视频| 草草影院视频在线观看视频 |