哈囉中臺業務 Flutter 實踐

前言

=====

2021 年 5 月 22 日,哈囉技術沙龍 - 大前端的探索與實踐,在杭州成功舉辦。
以下是由 @石旭盼 分享的主題《中臺業務 Flutter 實踐》

分享大綱

本次分享我們從移動端跨端的歷史背景、哈囉出行在 Flutter 上的多方位實踐以及我們對 Flutter 未來的展望這 3 大塊,共 6 小點和大家一起分享一下我們平臺移動端和業務中臺在 Flutter 這個技術棧上的一些技術成果。

跨端技術的前世今生

Flutter 想必有些同學已經很熟悉了也在實際業務中接觸過,它是 Google 近幾年新出的一個全新 跨端技術框架,我們開發者可以使用 Dart 語言去構建 iOS 和 Android 應用。

爲了讓大家更好的瞭解 Flutter 技術棧,我們先來回顧一下移動端跨端技術的一些歷史背景。

我們可以大致將跨端技術的歷史分爲 3 個時期:

Hybrid 時期

時間可以追溯到 2009 年前後,這個時期業界會陸陸續續使用 HTML、JS 等 Web 技術棧,再結合上移動端的 WebView 容器來進行一些 APP 的業務開發。

同時 Webview 容器通過對原生的一些能力的封裝,提供給 H5 頁面去使用來豐富 H5 側的能力以及打通 H5 和移動端的原生能力;

但是 瀏覽器內核的渲染獨立於系統組件,比較難保證原生體驗,渲染的效果和 性能也會差一些。

因此我們把這個時期稱爲 Hybrid 時期。

DSL 映射時期

我們再來到了 2015 年,這一年 Facebook 推出了 React Native 這個框架,他與 Hybrid 最大的區別在於 View 渲染體系的不同,RN 拋棄了較低效的瀏覽器內核渲染模式,使用自定義的 DSL 映射對應的平臺組件,然後渲染成原生平臺的組件的方式來進行頁面渲染。

但是這種渲染方式還需要 JS 和 原生之間頻繁的通信,因此在有些場景會出現卡頓、白屏等一些性能問題,而且也會出現 iOS 和 Android 兩端 UI 細節上的不一致性等問題。

因此我們把這個時期稱爲 DSL 映射時期。

自繪製引擎時期

接下來再來到 2018 年,Google 在這一年推出 Flutter,它通過 Dart 語言來開發 UI 組件,所有的組件都基於自己的 Skia 引擎進行渲染;基於這套自繪引擎 Skia,Flutter 不僅僅做到了消除平臺之間的差異,而且在性能上也做到了與原生平臺相媲美;

於此同時 Flutter 也擁有高性能的 與原生平臺通訊的 Channel 機制 以及 完善的研發工具鏈。

因此我們把這個時期稱爲自繪製引擎時期。

好的,跨端技術的年代背景我們大致瞭解了;那我們再來對比一下這 3 個時期的跨端技術棧他們的優缺點。

各時期橫向對比

我們分別從 開發語言、渲染方式、性能表現、研發效率、多端一致性、動態化以及社區生態的活躍度,這幾個緯度 橫向對比一下他們,很清晰的看出 Flutter 除了動態化的這個特性不足以外,其餘特徵都優於 RN 和 H5。

因此對於實際的項目而言 Flutter 的高效率、高性能、多端一致性以及性能表現上也已經具備大規模商用的標準。

這也是爲什麼 Flutter 從推出以來熱度一直高漲,而且目前在全球有大量的研發團隊陸陸續續的在實際項目中去使用它。

上圖就是今年 Google I/O 大會上的數據。目前在 Google Play 上,已經超過 20 萬 個應用在使用 Flutter 了。Flutter 已然成爲目前最流行的跨端技術框架了。

Flutter 架構設計

接下來我們再來簡單的回顧一下 Flutter 的架構設計。

Flutter 的架構主要分爲三層,我們基於最上面的 Framework 層提供的能力進行 App 開發,並且運行在中間的 Engine 層,Engine 層也爲我們提供了一些跨平臺能力的支持和適配,當然我們也得益於 Engine 層的 Skia,Flutter 纔可以自渲染 UI 組件,並且消除平臺之間的差異,在渲染性能上也做到了與原生平臺相媲美;

最下面一層就是嵌入層,就是把 Flutter 嵌入到原生平臺中去,包括會去做 Suface 的設置、線程設置以及插件等等。

多方位實踐

哈囉出行 Flutter 體系化建設

在瞭解我們哈囉出行在 Flutter 上的一些實踐之前,我們先來簡單的瞭解一下哈囉出行的 Flutter 體系化建設是怎樣的。

哈囉 Flutter 業務使用情況

到目前爲止我們已經有 3 個 APP,9 條以上業務線 和 100 多個頁面 在使用 Flutter 技術棧了,於此同時在未來我們還會不斷有業務線,尤其是新業務都會優先去考慮使用 Flutter;而且這些業務都是基於我們現有的哈囉 Flutter 體系完成業務研發的。

那麼在這麼多業務場景都在使用 Flutter 的時候,我們肯定會遇到很多技術問題和痛點。

本次分享我們總結了其中 2 個比較有意思和代表性的問題,和大家一起分享一下我們是如何利用技術手段去解決它們的。

首先,我們在平常的業務研發和需求迭代中,隨着 Flutter 不斷的在各個業務線中去應用,我們會遇到問題就是:

“如何能快速的將已有的原生的基礎技術能力和中臺業務能力賦予 Flutter,快速的完善起 Flutter 體系化的能力?”

其次,在現有功能完善的業務下,也不斷會有新增的業務需求,那麼我們也會遇到就是:

“我們怎麼才能更好的利用 Flutter 來提高現有業務原生側的研發效率?”

我們把這 2 個問題都拋出來了,細心的同學可能已經發現了這 2 個問題其實就是原生和 Flutter 之間的相互依存,將原生能力賦予 Flutter,提升 Flutte 的能力;將 Flutter 跨端能力賦予原生,來提升研發效率。

哈囉 Flutter 架構概述

我們再來整體看一下我們哈囉出行 Flutter 架構概覽,主要分爲 4 層:

從下到上分別是 基礎能力層,這一層最主要的是 我們 哈囉出行的原生能力,它包括 基礎技術能力 和 業務中臺能力;當然還有一些三方開發庫的能力和 Android、iOS 平臺的能力。

再上面就是能力層,這裏就是我們 哈囉 Flutter 最核心的能力了,它包括 Sparrow 微服務容器、Lumos 跨端業務容器,還有 HelloFlutterUI、HelloCache 多端一致存儲框架、HelloRouter 多端一致路由庫等等其他的技術能力。

再上面就是 我們的業務模塊了,各業務均基於我們的能力層去研發業務;

最上面就是 產物層了,我們最終會把 Flutter 構建成一個整體的二進制產物,再集成到我們的 App 中去。

在我們的能力層,有 2 個比較重要的容器:

一個是 Sparrow 微服務容器,我們會利用它來解決剛纔說的問題 1;

另一個是 Lumos 跨端業務容器,我們利用它來解決問題 2;

微服務容器

上述章節中,我們也提及到在各個業務線不斷的引入 Flutter 的時,我們急迫需要將原生平臺上已有的中臺業務能力和基礎技術能力賦予 Flutter,讓我們快速搭建起 哈囉 Flutter 的體系化;同時也能搭建統一 哈囉 Flutter 開發行爲,避免無效、重複的建設,也能加速業務變現,以及加快跨端技術棧的轉型、降低技術研發成本、實現多端的一致性等。這也正是我們設計微服務容器的初衷。

我們叫這個微服務架構爲 Sparrow,中文翻譯是麻雀,有着麻雀雖小五臟俱全的寓意。但是這隻麻雀如何能功能強大到五臟俱全呢,當然要羽翼豐滿了,所以我們稱每個獨立微服務爲羽毛。

那我們來看一下這隻麻雀的架構是怎樣的?

微服務架構設計

我們先簡單的說一下 Sparrow 的架構原理:

Sparrow 內部也是分層架構,其中最主要的部分就是中間的服務層,也是 微服務容器的核心能力層。

它從依次有 業務微服務、基礎微服務以及三方微服務能力,而且各個微服務之間都相對獨立;各個微服務內部會各自封裝實現的細節和數據處理,並將對應的原生能力通過 Sparrow 的統一的 API 層提供給最上層的 Flutter 業務層去使用。

因此我們就能快速的將已有的原生業務中臺能力和基礎技術能力直接賦予整個哈囉 Flutter 體系了。

微服務容器原理

接下來我們看一下在實際業務開發中如何使用 Sparrow 微服務容器的。

首先,我們只需要將已經實現好的原生能力通過 Sparrow 的註解和定義好的唯一 Action 標識進行微服務的註冊,接下來只要在 Flutter 側業務層 通過對應的 Action 就能獲取到原生側的對應能力了。

是不是很簡潔而且方便使用;那我們這個微服務架構的內部機制是怎樣的做的呢?

首先是服務註冊:

其實現的核心是利用編譯期註解,來收集和歸類全部微服務註冊到微服務容器中;

Android 側使用 java 的註解,iOS 側也一樣 只是利用 OC 宏 去模擬類似註解的形式;在編譯期我們會收集註冊的全部微服務,統一到一個文件中;在應用啓動後會讀取這個文件,將全部的服務列表註冊到微服務容器中,等待 Flutter 業務層去調用。

其次是調用流程:

這裏我們用實際的一個業務例子來說明一下,我們的火車票業務爲了提升用戶的購票體驗,當用戶購票時我們需要直接填寫用戶當前位置最近的高鐵站來方便用戶購票;這個時候我們的火車票購票業務就需要原生的定位能力了。

所以,我們火車票 Flutter 業務層只需要通過微服務容器發起獲取定位數據的需求,微服務容器會根據定位微服務的 Action 調用到 Flutter 側的定位微服務,然後微服務通過容器將 Action 和 請求信息進行模型轉換,再利用 Flutter Channel 通道,將數據傳遞到微服務容器的原生側,原生側會根據 Action 進行服務搜索 和 服務轉換 或 服務的初始化,待找到原生服務後,將數據分發給定位的原生組件中,待原生組件獲取到定位信息後,會將所需的數據 原路依次返回給 火車票 Flutter 業務層。

就這樣我們完成了一次 Flutter 業務 調用原生能力的需求。

至此我們借用微服務容器化的方式將已有的原生業務中臺能力和基礎技術能力,直接賦予 Flutter 側,並快速的搭建起哈囉 Flutter 的體系了。

跨端業務容器

我們業務中臺的消息平臺、支付平臺以及用戶平臺等等一些列業務;這些業務原生時期都已經具有完備的功能了,但是業務側還會不斷的有新的需求,如果還是基於之前原生開發模式去做的話,那我們需要分別在兩端投入研發同學,但是呢可能會出現研發同學不夠,偶爾也會出現兩端不一致的情況,而且這種研發模式整體的研發效率也很一般。

所以我們需要一個能在業務邏輯開發上能減少研發同學的投入、而且保證兩端一致性以及保留原生 UI 頁面體驗的一個 跨端業務容器。

這就是我們 跨端業務容器 的推出背景;我們稱這個 跨端業務容器 爲 Lumos。

Lumos 是《哈利波特》中的一個 照明咒,寓意更開闊明朗的未來,當然我們也藉此 寓意着 通過我們的這個跨端業務容器 能給哈囉業務發展帶來開闊明朗的未來。

跨端業務容器架構設計

上圖是跨端業務容器 Lumos 的分層架構設計,我依次從上往下看,首先是

所以 Lumos 的目的就是提供一個跨端的、一致性的、可複用的 Flutter 跨端業務容器;在保證研發提效、多端一致性的同時,也能兼顧 原生頁面的流暢體驗的需求。

跨端業務容器原理

接下來我們先看個實際例子,我們是如何使用 Lumos 這個跨端業務容器的?

圖示顯示的例子,首先要在 Flutter 側的業務層 實現業務邏輯,並繼承 Lumos 接口將其註冊到跨端業務容器中,跨端業務容器會在 Flutter 引擎初始化後,將註冊的業務能力統一提供到跨端業務容器的原生側,等待我們原生側使用。

當原生側需要處理業務時,只需要通過 跨端業務容器 發起需求,跨端業務容器會通過內部機制 調起 Flutter 側註冊的業務,待邏輯處理完成後,再原路將數據返回給 業務原生層 供業務進行下一步的操作。

也是很簡單和方便的使用,那這個跨端業務容器的內部機制是怎樣的呢?

我們繼續拿實際的業務場景來說明下,就拿我們最熟悉的賬號模塊的用戶登錄功能來作爲例子吧;在我們某一次新需求開發時就將新的登錄需求功能利用跨端業務容器做到了 Flutter 層,並提供給原生的 UI 頁面使用。

基於上述我們跨端業務容器整體的流程大致是,當賬戶模塊的原生 UI 層 發起 用戶登錄需求時,將登錄功能 URI 和業務參數提供給跨端業務容器,跨端業務容器將信息封裝和處理後,再經 Flutter Channel 傳到 跨端業務容器 Lumos 的 Flutter 側,Flutter 側通過功能 URI 進行檢索,待命中到對應的賬號模塊的登錄能力後,再將數據等一列信息分發到賬號模塊 Flutter 層進行業務處理,待處理完成後,會將結果數據進行信息轉換後,通過 Flutter Channel 返回給原生 UI 層,原生 UI 層 再根據實際的結果進行 UI 頁面的操作。

就此我們完成了一次完整的原生 UI 結合跨端業務容器處理了一個實際業務需求的流程。

當然,跨端業務容器 Lumos 的使用場景不只侷限於業務邏輯的開發提效。業務所處領域的數據,流程,規則等是可以通過 Lumos 統一集中在一起,通過狀態集中管理來更新,監聽,並維護我們的應用。

小結

經過對上述 2 個問題的解決以及解決方案的架構設計;我們不難發現 原生側 和 Flutter 之間其實就是一個相輔相成的關係,也沒有誰一定要代替誰這麼一說。

還是圍繞着將原生能力賦予跨端平臺,來提升跨端平臺體系化的能力;再通過跨端能力賦予原生,來提升原生側研發效率。

這也是我們近幾年甚至未來長期的移動端研發模式。

展望未來

我們使用容器化技術手段,優化了業務需求交付的模式、快速搭建起哈囉 Flutter 體系,同時也加速了新業務的變現、提升了業務研發效率、解決多端一致性等問題。

未來我們還會在跨端之間多媒體資源內存共享、Flutter 穩定性監控和建設、Flutter 動態化實踐以及 Flutter SDK 版本平滑升級等方面繼續探索和驗證。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/joIAQUA82G4CNa2AwPlfgw