Hybrid框架之交互通信篇
前言
雖然有些應用在使用React Native或Weex開發,但綜合來看,業內還是以混合開發模式為主,從我們自家的App來看,H5業務所占比重越來越高,目前大概占到35%左右,因此一套好的Hybrid開發框架必不可少。
混合開發的一般原則為交互較少、上線周期短、展示性質的頁面使用H5開發,如節日活動頁、商品秒殺頁面等。Hybrid框架要考慮的事情非常多,如頁面加載速度、預加載及緩存機制、與原生交互通信、不同機型兼容等問題。
本文的關注點僅在于Hybrid框架交互通信的設計與實現,框架的其他方面日后分享,感興趣的也可以留言探討。
交互通信類型
從大的范圍來看,可以分為三類:
- H5向Native通信,以下為常見場景:
- H5打開一個原生界面,H5只作為一個入口,后續邏輯均在原生界面處理
- H5喚起一個原生界面執行一些邏輯,需要將結果返回給H5
- Native向H5通信
- 通常表現原生界面將某些結果傳給H5頁面或觸發某些H5的行為
- H5頁面之間通信
- 如果H5項目有多個獨立頁面,頁面之間可能需要通信
設計與實現
設計原則
交互通信實現
H5向Native通信
如果不用JavaScript注入的方式,最常見的做法是利用自定義的交互協議,通過public boolean shouldOverrideUrlLoading(WebView view, String url)攔截并進行原生處理。因此為了適應上述提到的一些場景,協議的格式就尤為重要。
H5打開一個原生界面,H5只作為一個入口,后續邏輯均在原生界面處理,無需返回值給H5
對于這種需求,通常使用路由協議來實現,如下:
sample://route/module ID/sub ID
Native端接收到H5觸發的此種協議,就會根據模塊ID及子ID跳轉到某個原生頁面。上述協議示例只是一種最通用的情況,還可按一定規則擴展協議以應對其他邏輯。關于模塊路由的設計可參考之前的一篇文章:一種Android客戶端架構設計分享。
H5喚起一個原生界面執行一些邏輯,執行完成后需要將結果返回給H5
常見的示例如H5中調用原生的登錄模塊,用戶登錄成功后重新返回到H5頁面,同時需要將登錄狀態、用戶Urid等返回;另一種場景如H5調用原生地址管理模塊,選擇一個地址之后,將地址數據返回給H5。這兩個例子雖然也可以完全用H5實現,從而避免交互,但采用H5與原生交互的方式優點如下:
對于這種需求,其實就是一種需要帶回調的通信,即H5跳轉原生界面執行完某操作后,需要將結果返回給H5。
以H5調用原生登錄并返回H5刷新為例,可設計協議如下:
sample://login/callback
Native端接收到此類協議則會調用原生登錄界面,同時保存下callback。當原生界面登錄完成,可使用消息分發機制(一種Android客戶端架構設計分享 中也有說明)通知WebView調用此JavaScript回調,所需的傳值如登錄狀態、用戶ID可封裝為JSON格式,通過callback參數方式返回給H5。H5中處理此回調提取返回值,如登錄成功,接下來可執行用戶登錄后相關的刷新操作。
Native向H5通信
普通的單向交互
此種通信方式比較簡單,就是通過WebView去加載JavaScript的方法或回調函數,傳值可通過參數方式,跟上文的callback相同。
Native容器(Activity或ViewController(iOS))向H5暴露生命周期狀態
在混合開發中,往往為了模擬原生任務棧的效果,每打開一個新的H5總會開一個新的包含WebView的Activity(或者WebView也可直接位于Fragment中,Fragment位于Activity中)。這樣用戶體驗就接近原生效果,返回時會返回上一級包含H5頁面的Activity。
一種場景如A頁面跳轉到B頁面,從B頁面返回A頁面,此時純H5對頁面狀態不易監測或者監測不準確,有時H5端會有此種需求,因此可利用原生頁面的生命周期獲取頁面狀態。在原生代碼中根據原生頁面的生命周期觸發一個JS回調,有需要監聽頁面生命周期的H5自行實現該回調即可,實現后JS即可獲取原生頁面狀態從而進行對應處理。
由于H5沒必要知道原生界面的所有生命周期狀態,可能僅僅對如下兩種狀態感興趣:
因此協議可定義為:
sample://lifecircle/status
status狀態值為PAUSED或RESUME 。
注意事項:
H5頁面之間的通信
對于SPA(Single Page Application),此為單頁面應用,多個鏈接的跳轉都在同一個WebView中,上述需求是不必要的,此種實現體驗不太好。
對于MPA(Multiple Page Application),此為多頁面應用,為了追求原生體驗,往往每一個H5總會新開一個Activity頁面,前文也有提到,MPA是我起的名字,理解意思即可。在這種情況下,不同的H5頁面實際上是處于不同的Activity或Fragment中,也是在不同的WebView中,因此H5頁面間的通信成為必要。
假設一種場景如A頁面打開B頁面,B頁面打開C頁面,C頁面需要向A頁面通信,之間隔著B頁面。理論上兩個通信的頁面間可以有0~N個中間頁,都能夠支持。
由于是不同的Activity和不同的WebView,因此H5頁面之間無法直接通信。有了上文講到的H5和Native之間互相通信的基礎,此處可以換一個思路,將H5與H5的通信轉化為兩個Native頁面的通信。
下面是一個原理圖:
原理說明:
前提條件為模擬原生頁面回退棧的效果,每個Web頁都用單獨的WebView打開。
上圖例子中有3個Web頁面,邏輯為A頁面打開B頁面,B頁面打開C頁面,以C頁面的H5向A頁面的H5通信為例。
H5頁面間通信原理本質是利用原生頁面間的通信方式。H5頁面的直接容器為WebView,再往外一層的容器為Activity(Android)或ViewController(iOS),為了兼容嵌入式的WebView,H5最好向WebView注冊事件而不要向Activity注冊。在實現上應抽象封裝一個公共的WebView(相信大家日常開發中都是這樣做的),統一接收H5事件注冊及事件觸發通知。
首先A頁面的H5需要向容器注冊事件,JS需要調用的注冊協議為:
sample://register/custom_event_name
**注意:**custom_event_name為開發者自定義的事件名稱,不同頁面可注冊相同的事件名,那么多個頁面都會響應事件;一個頁面中若注冊多個相同的事件名,則會覆蓋,僅響應一次,也不推薦如此使用。
注冊完成后,每個容器實例會維護一個注冊過的事件名列表。
當C頁面要向A頁面通信時,C頁面中JS需要觸發的協議為:
sample://notify/custom_event_name/callback/params
**注意:**custom_event_name要跟注冊事件名一致,Native端用來匹配決定哪個頁面響應事件;callback則為A頁面收到消息后要執行的回調;params為H5間通信需要傳遞的參數,即為A頁面執行callback回調時的參數,其格式根據需求可自定義,復雜的數據可使用JSON串。事件名稱、回調名稱、回調參數可自由定義,均跟Native端無關。
協議sample://notify/custom_event_name/callback/params中的callback需要在A頁面的H5中實現,否則無法響應C中H5對A中H5的通信。
上述過程中,原生容器C向A通信也是利用一種Android客戶端架構設計分享 中介紹的消息分發機制。當然也可以用EventBus之類的事件總線替代,在iOS中可使用廣播實現。
總結
Hybrid框架中的交互通信主要是以上幾種,這些基本能夠滿足日常開發需求。交互原理也比較簡單,如有其它特殊交互也可擴展,相信大家能夠根據上述設計原理自己實現,有時間的話后面會提供一個框架實現的demo。
總結
以上是生活随笔為你收集整理的Hybrid框架之交互通信篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中的scrapy爬虫_Pyt
- 下一篇: 计算机类智能问答助手论文,写论文不用愁,