VasSonic Android源碼解析

VasSonic是騰訊推出的爲了提升H5頁面首屏加載速度而推出的高性能Hybrid框架,目前普遍應用在QQ商城等Hybrid界面中,以提升用戶體驗。javascript

https://github.com/Tencent/Va... GitHub地址html

一.實現原理

幾乎全部的Hybrid界面都以WebView界面爲載體,H5界面加載的時間主要消耗在在WebView初始化、網絡請求、WebView渲染三個部分。WebView初始化與WebView渲染均是100ms的時間量級,其中最主要的時間瓶頸在網絡請求上,尤爲是弱網狀況下,其消耗時間將達到s級,致使H5界面白屏時間較長或沒法正常打開。
爲了解決這個問題,WebView中提供了
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
函數負責攔截並加載html中用到的資源文件,以此爲基礎,引出VasSonic的核心思想並行加載,本地緩存,模板變動。
總體的思路即是利用WebView初始化的時間並行的進行網絡請求,並利用緩存進行預加載,網絡請求完成後再把變化的部分返回給瀏覽器利用JS進行數據變動。java

二.核心流程SonicSession

整個源碼咱們應以SonicSession文件爲切入點,它管理整個並行流程,負責獲取緩存,網絡請求,並以向外暴露抽象方法的方式交給子類處理錯誤處理,預加載,模板變動,並提供與JS的惟一交互出口,下面咱們具體走一遍它的流程。
當WebView啓動初始化前,便會調用SonicSession的start方法,而後會在子線程調用runSonicFlow方法,開始並行處理。git

clipboard.png

在runSonicFlow中,咱們會嘗試獲取緩存,並交由子類的handleLocalHtml進行處理,預加載就能夠在這裏處理。github

clipboard.png

然後會運行handleFlow_connection方法,首先他會獲取SessionConnect,以後會添加本地緩存的一些信息從而獲取變化後的網頁,進行connect操做後,獲取到responseCode,會交給SonicSession的子類進行hanldeFlow_304,handleFlow_HttpError,handleFlow_ServiceUnavailable一系列錯誤處理。
以後會判斷緩存是否爲空,緩存爲空的回話會交由子類的handleFlow_FirstLoad處理,不爲空的話回判斷是Template變化的話會交由子類的handleFlow_TemplateChange處理,Data變化的話會交由子類的handleFlow_DataChange處理。json

clipboard.png

可見,SonicSession主要向子類在幾個關鍵的節點上暴露方法,獲取緩存後子類調用handleLocalHtml處理,網絡鏈接結束後會根據錯誤碼等信息交由子類的hanldeFlow_304, andleFlow_HttpError, handleFlow_ServiceUnavailable 進行一系列錯誤處理,獲取網絡請求成功後,若是緩存爲空,會調用子類的handleFlowFirstLoad處理,緩存不爲空的話,會根據結果的header信息判斷是模板變化仍是數據變化,分別交由handleFlow_TemplateChange,handleFlow_DataChange處理。跨域

在SonicSession中,一樣會提供一些方法用於各類事件的回調。
SessionClient建立完成後調用OnClientReady方法,這個方法標識着WebView已經初始化完成。
當WebView開始加載資源後,會被shouldInterceptRequest方法攔截,會調用咱們的OnClientRequestResource方法,標識着WebView開始加載數據。瀏覽器

clipboard.png

當WebView渲染完成,會調用OnWebReady方法,其中會攜帶着JS的回調方法,最後會經過setResult調用H5的回調方法。緩存

clipboard.png

三.兩種SonicSesion的具體實現

由上面對SonicSession的分析可知,子類SonicSession所須要關注的點有
調用loadUrl或loadUrlWithBaseUrl啓動瀏覽器加載流程。
賦值pengdingWebResourceStream,並返回給瀏覽器解析。
模板和Data變化通知給瀏覽器作相應處理。
攔截資源實現加載。
調用setResult進行瀏覽器回調。安全

1.StandardSonicSession
基於安全性上的考量,StandardSonicSession模式下僅支持loadUrl。
在瀏覽器準備完成後,咱們就能夠直接調用loadUrl,因此在OnClientReady中,咱們直接就能夠調用loadUrl。

關於pendingWebResourceStream的賦值,在上面一條線的流程中完成。
WebView支持邊加載邊渲染的特性,咱們能夠將流傳進去後,繼續進行寫操做,因而定義了SonicSessionStream,以後咱們會介紹到。
因此須要判斷數據是否接受完成,對賦值操做作不一樣的處理,而後再作保存數據的操做。

clipboard.png

clipboard.png

下面咱們看一下StandardSession的流程到底是怎麼處理的,哪些地方對pendingWebResourceStream進行了操做。

clipboard.png

在上面的流程圖中能夠看到會根據模板與Data的變化進行不一樣的處理。
由上面的分析可知WebView在loadUrl後,可在onClientRequestResource方法中對瀏覽器資源的加載進行攔截,注意!這個方法內只會攔截咱們的html文件,進行文件流的傳入,資源文件並不會攔截。這個方法作了對網絡流的等待,等待pengdingWebResourceStream有值以後,就會將流返回給瀏覽器進行加載渲染。
setResul在onWebReady中需吊用一次,在這裏咱們肯定回調方法。
之後每次流程發生轉變的時候需調用一次,能夠幫咱們明確每一次請求走的流程,更主要的是當Data變化時,咱們能夠調用瀏覽器的回調方法。

2.QuickSonicSession

與Standard核心的不一樣點便在於能夠經過loadBaseUrl實現加在緩存的html字符串,速度上有必定優點,但安全性上有必定問題,經實測速度優點不明顯。
在實現上,和Standard模式咱們須要關注變化的點主要就是不能在OnClientReady中不能直接調用loadUrl,須要在有緩存的時候loadBaseUrl,而後本身構造header,其餘變化不大。

四.具體流程

下面咱們梳理下具體的流程,首先咱們展示的是初始化的流程。

clipboard.png

下面展示的是SonicSession start後的流程。
clipboard.png

五.具體問題處理

不一樣線程間等待如何調度與通訊
網絡請求所在的業務在Sonic子線程中,主要經過主線程的handler與WebView所在的主線程通訊。
clipboard.png
clipboard.png
clipboard.png
WebView所在的主線程主要經過控制Atomic變量對子線程進行控制。
clipboard.png
clipboard.png
當WebView加載完成,網絡請求的結果還未賦值時,將經過同步鎖的方式等待網絡請求的結果。
clipboard.png
其實WebView是支持邊加載邊渲染的特性的,只要將數據流傳遞給WebView便可,因而提供了SonicSessionStream支持這種特性,下面會介紹到。

如何作網絡流和內存流的橋接
能夠看到網絡數據完成時,直接將數據放入Stream中,而未完成時,則建立了SonicSessionStream。
clipboard.png
其中上面的outputStream表明着已讀取到內存中的memStream,responseStream則表明着仍未讀取的netStream。
clipboard.png
經過重寫SonicSeesionStream的read方法便可實現橋接。

如何作局部刷新
當緩存數據網頁加載完成,即調用onWebReady後,會經過javascriptInterface將js的回調方法返回給App。
當服務器想通知客戶端局部刷新時,會經過頭部的template-tag通知,並返回data的json。
經過比較本地的data與新data返回差別data,並將結果賦值給pendingDiffData。
而後會經過setResult調用js的回調方法,完成局部刷新過程。

緩存文件儲存
進行緩存時,會計算返回結果的sha1值,並存入sp中。
獲取緩存時,會從sp中讀取文件的sha1值進行比對。

head管理(跨域問題)

相關文章
相關標籤/搜索