前端解讀Webview


  作為盛行已久的開發方式,Hybrid的相關介紹已經是相當普遍了。不過看到博客園里基本上都是從android或者ios的角度來講解的,對於h5的前端來說看起來只能是一直半解。感覺有必要從前端的角度來理解和解讀一下Hybrid相關內容。作為移動開發技術中不可或缺的一項,Hybrid 憑借其特有的優勢牢牢的占據了一席之地。這里就不展開討論討論Hybrid的優劣了(想了解請查看http://www.cnblogs.com/yexiaochai/p/4921635.html

   html作為一種解釋性語言,需要運行於解釋器之上。我們常用的的pc端瀏覽器就是其一。作為移動端的一種混合開發的模式,Hybrid是如何解決這一問題的呢。這就引出了webview這一概念。hybride中的h5依托於webview容器來(對應於ios和安卓,應該有不同實現,這里就不是前端可以細說的了)解釋運行。下面就看一下webview相關的部分。

  一、webview的概念:

  先放一段基本定義:A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.
        自己的理解:webview用來展示網頁的view組件,該組件是你運行自己的瀏覽器或者在你的線程中展示線上內容的基礎。使用webkit渲染引擎來展示,並且支持前進后退等基於瀏覽歷史,放大縮小,等更多功能。
      簡單來說WebView是手機中內置了一款高性能 webkit 內核瀏覽器,在 SDK 中封裝的一個組件。不給過沒有提供地址欄和導航欄,只是單純的展示一個網頁界面。

  作為hybrid中的webview,相比較於native中原生組件,給人最直觀的印象可能就是慢,不給過為什么這么慢呢,當然影響因素是很多的,除去一些外部因素。與webview自身的初始化和加載過程也是分不開的 ,下面來看一下webview的初始化過程

  二、webview初始化


  當App首次打開時,默認是並不初始化瀏覽器內核的;只有當創建WebView實例的時候,才會創建WebView的基礎框架。所以與瀏覽器不同,App中打開WebView的第一步並不是建立連接,而是啟動瀏覽器內核。

  在瀏覽器中,我們輸入地址時(甚至在之前),瀏覽器就可以開始加載頁面。

  在客戶端中,客戶端需要先花費時間初始化WebView完成后,才開始加載。

  而這段時間,由於WebView還不存在,所有后續的過程是完全阻塞的。簡單對比下兩個的渲染過程:

      瀏覽器: 

      

       webview:

       

  可以看出在webview初始化之前,后面的步驟根本無從走起,耗時當然變長了。並且每次打開webview都要走這個過程。

  三、Webview優化


  從上面可以看出來webview相對瀏覽器來說,影響點在於webview的初始化並且阻塞后面action的這個過程,其實說來也簡單(我只是說概念上,native的東西對我來說還是很難的)對應問題的兩種表現形式,對應有兩個方向上的優化。
  3.1、減少webview初始化的消耗


  鑒於每次打開都要進行初始化webview組件的這種場景,很自然的對應起來一種設計模式即單例模式,既然每次都要走相同步驟完全可以實例化一個全局對象,從而免去其他過程的消耗。當然客戶端的同學們也是這樣做的: 初始完全可以建一個全局,隱藏的webview。以供使用。省去了每次的初始化過程。

      不過這樣的缺點也是有的,就看如何取舍了:
  1、內存消耗:畢竟這貨一直存在
  2、頁面間的跳轉:畢竟只有一個webview實例,每次不同的加載需要處理的情況就比較多了。


  3.2、針對阻塞的過程
  每次的阻塞加載過程等待時間消耗也是很大的,就看能不能將串行的過程並行化。不過對於webview來說只能是這個樣子,不過我們需要跳出僅僅局限於webview的視線,webview僅僅是移動系統的一個組件,統計存在其他組件,網絡請求的過程完全可以交給native來做,也正如native一直在做的一樣,完全是可以處理該過程的。例如后端同學經常要開發的mapi,就是針對native的接口。

  四、webview與native的交互


  上面提到native可以並行執行網絡請求,以加快webview的呈現時間。又一個問題出現了,webview如何調用native接口去請求數據並獲取native拿到的數據呢。除此之外還涉及到調用底層api等需求都需要借助native實現,問題的核心就是兩者的交互如何實現,作為兩者之間的溝通橋梁,jsbridge就應運而生了。
  所謂交互無外乎兩大塊:一是h5調用native,另一個是native調用h5。
  一、Native調用JS:


  原生調用h5比較簡單,可以直接調用。畢竟這里存在一個宿主的關系,脫離了webview,js就沒有生命力了,而native其他功能是在webview外部的。所以反過來不能直接調用。
  例如有如下代碼:

1 <script type="text/javascript"> 2 function myFunc() { 3 return "Text from web" 4 } 5 </script>

  ios可以直接通過webview的屬性調用(前端只能從方法名來看了,將js代碼當做字符串讀出來再解析)

NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"myFunc()"];

  2.H5網頁的JS調用Native


  本質還是用uiwebview的代理方法進行字段攔截(判斷url的scheme),實現js間接調用native的method。

  android可以直接給網頁中js函數注入一個原生代碼接口。

1 //相當於添加一個js回調接口可以直接通過window全局對象調用對應接口了:
2 mWebView.addJavascriptInterface(this, "native"); 3 <button onClick="window.native.actionFromJs()">點擊調用Native代碼</button>

  ios說起來也是注入只不過沒有android那么方便。
      在 webView 的 delegate 的 - (void)webViewDidFinishLoad:(UIWebView *)webView 里用下邊的方式注入 JavaScript
     

 1 NSString *js = @"(function() {\  2 window.JSBridge = {};\  3 window.JSBridge.callFunction = function(functionName, args){\  4 var url = \"bridge-js://invoke?\";\  5 var callInfo = {};\  6 callInfo.functionname = functionName;\  7 if (args)\  8 {\  9 callInfo.args = args;\ 10 }\ 11 url += JSON.stringify(callInfo);\ 12 var rootElm = document.documentElement;\ 13 var iFrame = document.createElement(\"IFRAME\");\ 14 iFrame.setAttribute(\"src\",url);\ 15 rootElm.appendChild(iFrame);\ 16 iFrame.parentNode.removeChild(iFrame);\ 17 };\ 18 return true;\ 19 })();"; 20 [webView stringByEvaluatingJavaScriptFromString:js];

  以前端的角度來看這段代碼,是在 window 里創建一個叫 JSBridge 的對象,然后在里邊定義一個方法 callFunction,

  這個方法的作用是把兩個參數打包為 JSON 字符串,然后附帶到我們自定義的 URL bridge-js://invoke? 后邊,

  最后用 IFRAME 的方式來加載這個 URL當加載 IFRAME 的時候,就會調用 webView 的 delegate 的

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 

(即特定方法來處理)方法。對url進行處理,把以約定字符開頭的url后面的json解析出來,執行對應方法。

        至此webview與native的交互即jsbridge的實現從前端的角度也大概就是這樣子結束了,關於上面的客戶端代碼可以自行研究,不給過前端來看也是不太難看懂。以上就是我對webview的理解了,歡迎大家相互交流共同進步。

 

參考文章:WebView性能、體驗分析與優化

     淺談Hybrid技術的設計與實現

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM