有贊移動消息卡片動態化方案實踐

概述

消息業務作爲有贊移動的共享業務,在微商城、零售、美業等 B 端 App 中承擔着多客服的角色,多客服是有贊爲商家提供的連接商家和買家的即時消息客服工具;在精選、有贊客 C 端產品中扮演着用戶聯繫商家的角色。在整個有贊產品中,是商家和用戶溝通的橋樑,起着非常重要的作用。

痛點

我們通常來講把出現在消息會話頁面內的內容稱做消息卡片,目前消息業務常見的消息卡片有文字、富文本、語音、照片、視頻、通知消息,除此之外還有訂單詳情、推薦商品、覈對訂單等共計30餘種消息卡片。目前我們消息卡片都是採用原生來開發,隨着業務的日益增多,消息卡片的數量也在成倍的增長,業務方經常提出增加卡片的需求,去開發和維護這些卡片工作量比較大,並且依賴業務方的客戶端發版,不夠靈活。

現狀

目前消息業務在 iOS 端和 Android 端均採用二方庫的方式開發,供各個有讚的 App 接入,在 iOS 中採用 Cocoapods 進行二方庫的依賴,Android 採用 gradle 來進行二方庫的依賴;如果業務方需要增加一種消息卡片從開發到上線按照正常的週期是1周到1周半,發版週期長、開發效率低。

動態化技術指不依賴 APP 發版,就能進行動態的增加或者修改來更新頁面的技術。對於消息卡片這種需要快速迭代、實時調整的業務,動態化具有非常重要的意義。主要優勢體現在:

  • 提高人效
  • 縮短版本迭代試錯週期
  • 解決版本長尾問題
  • 減少包大小等

整個消息的業務場景如下圖所示:

消息聊天以及消息模版都是由消息卡片組成

原生消息卡片

先來說說原生消息卡片的實現方案,這裏以 iOS 爲例。整體架構設計我們採用 TableView 作爲整個頁面的容器,採用 MVVM 的架構去設計,架構分爲以下模塊:

  • 消息卡片數據源配置類 Configurator 負責 VC 和數據源處理類的綁定以及消息管理處理
  • 消息卡片接口管理類負責接收/發送消息數據處理,重發的操作、界面接口(增、刪、改、查)
  • 數據源操作類 TableAdapter 負責 TabelView 的代理方式、數據源代理方法的實現,以及一些視圖刷新等相關操作
  • 消息卡片內容視圖工廠類 ContentFactory 會根據消息類型註冊對應的 ContentConfig 進行一個緩存
  • 消息卡片配置類 ContentConfig 是根據消息類型從工廠類中獲取的,返回當前消息卡片的寬高(size)、消息體 message、當前渲染的消息卡片視圖
  • 消息模型 layout ,根據不同的消息類型生成,會保存當前的消息體以及消息卡片的寬高,爲了提升性能,緩存在 TableAdapter 數據源操作類中
  • 消息卡片cell,根據後端下發不同的卡片類型,從消息卡片配置類中獲取不同的 contentView 加到 cell 中,進行消息卡片的展示
  • 消息卡片 contentView,負責消息卡片 UI 佈局、數據的渲染、綁定

整個架構如下圖所示:

消息原生架構圖

方案

關於動態化技術棧的選擇

上面介紹了 iOS 端消息卡片渲染架構設計,那麼爲了讓消息卡片具有動態化的能力,但是不會打亂現有原生架構的情況下,我們採用了結合 weex 技術棧來做這件事。爲什麼用 weex 來提供動態化這樣的能力?首先該技術棧已經在有贊移動中扮演者重要的角色,我們團隊之前已經做了 weex 無線開發平臺,我們團隊主導建設了 ZanWeex ,它是一整套解決方案,從開發、構建到發佈、熱修、數據、監控,全生命週期的平臺和工具,目前有贊業務很多模塊都是以 weex 來實現,也接入了長連接功能,無須重啓 App 實現實時下發的功能,對 weex 有興趣 的,可以查閱 weex官網。

因此我們的核心思路是利用 weex 來達到消息動態化的目的。

  • 創建 weex 容器,爲了避免容器臃腫, 這裏我們沒有選擇 ViewController 來充當 weex 的容器,而是用 View 來充當容器,裏面包裹了一個 WXSDKInstance 進行 weex 的渲染。
  • 原生端創建渲染 weex 的 TableViewCell,將 weex 容器視圖添加到 cell 的 contentView 中去,利用 TableView 的重用機制進行 cell 的緩存和重用。

動態化能力

技術架構設計

在架構設計上面,我們在以前原生的 MVVM 的基礎上,利用 JS 動態庫,配合 weex 達到動態化卡片的能力,做到了 App 不發版的情況下,只需發佈 weex 就可以動態添加消息卡片,也可以修改消息卡片的 UI 樣式。鑑於這樣的設計目標,在這個框架裏,主要考慮以下方面:

  • 在不改變原有原生架構的基礎上去做消息卡片動態化
  • 頁面佈局動態化,意思是頁面的排版佈局,可以通過 weex 端和 JS 端發佈來達到動態更新
  • 組件的複用,爲了在多種類型的卡片中保持良好的性能,需要對 weex 端容器進行緩存和複用
  • 開發、構建、發佈整個流程需要擁有一個完善的平臺

JS 動態庫

JS 動態庫是我們團隊出的一個動態化方案的框架,主要功能是提供動態下發的能力;快速修復線上問題;兩端特殊複雜的邏輯保持一致等。JS 動態庫也是利用 ZanWeex 平臺來開發、構建到發佈,一整套流程都是完善的,這裏我們不去過多的討論 JS 動態庫的相關內容,我們僅僅是用到動態下發的能力,核心思路是:

  • 利用 JS 動態庫根據消息類型下發對應的 weex 卡片的 url
  • 利用 JS 動態庫根據消息內容和消息類型來計算原生承載 weex 容器的 TableView 的 cell 寬高
  • 利用 JS 動態庫下發需要加載 weex 卡片的消息類型
  • 利用 JS 動態庫根據消息類型來判斷當前的 cell 是否是 weex卡片 cell

接入 JS 動態庫

  • 我們在 JS 動態庫中,暴露出獲取 weex 卡片對應的 url 方法,入參是消息類型
  • 獲取 weex 卡片所在的 cell 的寬高,入參是消息卡片內容和消息類型,JS 將卡片內容解析出來,進行高度、寬度的計算返回給原生。
  • 獲取需要支持 weex 卡片的消息類型,原生根據這些類型進行容器 cell 的註冊

性能

性能較好,在多個 weex 卡片消息交替出現的時候,爲了避免達到性能瓶頸,因此首先考慮到利用原生 TableView / RecyclerView 的重用機制,拿 iOS 來舉例,用 weex 的 url 和 TableView 的 identifier 做一個綁定,這樣不必自己去維護 weex 卡片的重用和回收。第一版做出來的時候發現,這樣在持續加載 weex 卡片的時候 WXSDKInstance 會不停的渲染調用 renderWithURL 方法,這樣無疑是消耗比較大的性能去創建 weex 視圖。因此我們在 weex 容器中做一個標記,記錄上次該容器加載的 url,每次在加載 weex 卡片 cell 的時候去判斷當前的 url 是否是上次記錄的 url,如果是,就說明這個類型的 weex 卡片之前已經渲染過,WXSDKInstance 實例可以拿到原生傳過來的數據進行 refreshInstance;否的話用 WXSDKInstance 進行 renderWithURL,這樣可以節省一次 render 重新渲染,從而解決卡片太多,上下滑動的時候會出現短暫的空白現象。

整體流程

  • 消息通道連接的時候,weex 模塊去拉取對應的註冊的 weex 頁面;初始化 JS 動態庫,其實也就是拉取 JS 相關的邏輯配置
  • 後端下發消息數據,經過數據解析器將消息經過轉化生成 layoutModel 緩存起來
  • 在消息卡片視圖工廠類 contentFactory 中,將消息類型傳到 JS 端來判斷當前消息類型是否需要註冊成 weex 卡片
  • 在獲取卡片寬高、消息模型的卡片內容配置類 contentConfig 中,將消息類型、消息內容傳到 JS 端,返回 weex 卡片寬高
  • 數據操作類去持有 LayoutModel 和 contentConfig 類,在 TableView 代理方法回調的時候,去加載對應的 weex 卡片和寬高,並且將 weex 卡片的url作爲 identifier 重用標記
  • TableView 加載 weex 容器的 Cell 時傳遞消息類型到 JS 動態庫,然後返回對應的 weex 卡片 url,然後根據 url 將消息卡片內容傳遞到 weex 容器端去進行渲染或者刷新

架構設計如下圖所示:

消息動態化架構圖

優化

目前整個流程已經上線,情況比較穩定,極大的提高了開發效率,增加/修改消息卡片做到完全動態化,但是目前我們的方案也有很多不足之處,比如我們期望更好的性能和更高的運行效率、更加動態化的事件處理能力、更加方便的開發體驗,對此我們也做了更進一步的規劃建設:

  • 組件創建、佈局計算、數據綁定機制、從 JS 端獲取數據做緩存的優化,提升性能
  • 規範事件點擊回調處理,提供跳轉商品詳情、訂單詳情、原生特定頁面 router 以及 webView 的事件處理
  • 拆分出動態化框架 SDK ,讓其他需要用到的業務可以接入,比如一些活動頁面

總結

以上是我們整個消息卡片動態化的整體方案,總結來講就是在原生架構基礎上配合 weex 技術棧、JS 動態下發,達到整個動態化的目的,可以算作一個輕量化的動態化方案,算是在動態化方面做一些嘗試,也希望可以和廣大開發同學一起交流。

參考鏈接:

本文轉載自公衆號有贊coder(ID:youzan_coder)。

原文鏈接

https://mp.weixin.qq.com/s?__biz=MzAxOTY5MDMxNA==&mid=2455761163&idx=1&sn=32e318bdf0c847021abc5e621193172c&chksm=8c68772ebb1ffe38768f187645f73848879ed6bd7baf8f50a4b6e81556dc8b7ab56868d22579&scene=27#wechat_redirect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章