Flutter 與 iOS 原生 WebView 對比

享物說發表於2019-02-28

本文對比的是 UIWebView、WKWebView、flutter_webview_plugin(在 iOS 中使用的是 WKWebView)的載入速度,記憶體使用情況。

測試手機:iPhoneX
系統:iOS12.0

載入速度對比

測試網頁開啟的速度,只需要獲取 WebView 在開始載入網頁和網頁載入完成時的時間戳,時間戳的差即為開啟網頁的時間。

WKWebView

extension WKWebViewVC: WKNavigationDelegate {

    public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.allow)
    }

    public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        startTime = Int(Date().timeIntervalSince1970 * 1000)
    }

    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let finishTime: Int = Int(Date().timeIntervalSince1970 * 1000)
        print("WKWebView \(finishTime - startTime)")
    }
}
複製程式碼

UIWebView

extension WebViewVC: UIWebViewDelegate {

    public func webViewDidStartLoad(_ webView: UIWebView) {
        startTime = Int(Date().timeIntervalSince1970 * 1000)
    }

    public func webViewDidFinishLoad(_ webView: UIWebView) {
        let finishTime: Int = Int(Date().timeIntervalSince1970 * 1000)
        print("UIWebView \(finishTime - startTime)")
    }
}
複製程式碼

flutter_webview_plugin

flutterWebViewPlugin.onStateChanged.listen((state) {
    if (state.type == WebViewState.finishLoad) {
        print('finishLoad:' + DateTime.now().millisecondsSinceEpoch.toString());
        setState(() {
            isLoad = false;
        });
    } else if (state.type == WebViewState.startLoad) {
        print('startLoad:' + DateTime.now().millisecondsSinceEpoch.toString());
        setState(() {
            isLoad = true;
        }); 
    }
});
複製程式碼

為了使差異更明顯,我們選擇較為複雜的 新浪首頁 進行載入的對比,為了減小網路對載入速度的影響,我們讓手機連線同一個網路,分別進行 10 次測試然後取平均值,另外,我們需要關閉 WebView 的快取,防止快取對載入速度產生影響:

private func delegateCache() {
    let cache = URLCache.shared
    cache.removeAllCachedResponses()
    cache.diskCapacity = 0
    cache.memoryCapacity = 0
}
複製程式碼
private func deleteWebCache() {
    let websiteDataTypes: Set<String> = WKWebsiteDataStore.allWebsiteDataTypes()
    let dateFrom = Date.init(timeIntervalSince1970: 0)
    WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes, modifiedSince: dateFrom) {

    }
}
複製程式碼
WebviewScaffold(
    key: _scaffoldKey,
    url: widget.url,
    clearCache: true,
    appCacheEnabled: false,
    .
    .
    .
);
複製程式碼

下面使筆者進行 10 次測試所得到的資料:

UIWebView WKWebView flutter_webview_plugin
0 4009 3384 3582
1 2856 3719 2869
2 2773 3258 3221
3 2776 3570 3178
4 2933 3386 3092
5 2679 3706 2956
6 2583 3707 3038
7 3145 2947 3015
8 3654 3038 3634
9 3258 3439 3132
avg 3066.6 3415.4 3171.7

結果讓我有點驚訝,一直以為 WKWebView 會是個王者。結果看,速度上 WKWebView 略慢一點,不過總體差異不大(該結果僅僅是測試新浪的結果,僅供參考啦)。

在這裡,筆者又加了一個測試,嘗試記錄從 viewController 的 viewDidLoad 到 webview 的 didFinish 時間,測試了新浪的資料,如下:

UIWebViewA: 4970、3808、3815、4250、3556 avg(4079.8) (載入完所有頁面)
UIWebViewB: 4103、3124、3070、3256、2835 avg(3277.6)(載入sina完畢)
WKWebView: 3672、3032、2892、2912、2739 avg(3049.4)
flutter_webView: 4532、3901、4310、3496、3378 avg(3923.4)

其中可以看到,webView 有兩行,UIWebViewB 的資料就是載入 sina 主站的時間;UIWebViewA 的資料是因為在載入完 sina 主站之後,新浪又載入了一個https://r.dmp.sina.cn/cm/sinaads_ck_wap.html,所以導致總時間延長,不過即使按照 UIWebViewB 的資料來比較,也是 wkWebView 略勝一籌。

此處可以看出 flutter_webView 使用的是 wkwebView,所以它吃虧的主要原因是 flutter 包了一層。

結論: 速度(didStart -> didFinish) UIWebView > flutter_webview > WKWebView 速度(viewDidLoad -> didFinish)WKWebView > UIWebView > flutter_webview

佔用記憶體對比

這裡檢視記憶體使用的是 Xcode 的 debug session 中的 memory,首先看之前測試時,連續開啟十次新浪的記憶體情況:

UIWebView.png

WKWebView.png

flutter_webView.png

接著我們在看一下開啟淘寶首頁的記憶體情況

UIWebView.png
WKWebView.png
flutter_webView.png

從圖上可以看出,WKWebView 在記憶體方面有很大的優勢啊,UIWebView 的記憶體是真的傷啊,然後 debug 看了一下 flutter_webView,他使用的就是原生的 webView。

他相比較原生 WKWebView 的記憶體開銷稍大一點,從測試表現來看,一般大個 30 MB 左右。

結論:記憶體 WKWebView > flutter_webview > UIWebView

HTML5 相容性對比

可以在 html5test 中對瀏覽器的相容性進行評分,通過測試發現得分分別如下:

UIWebView.png
WKWebView.png
flutter_webView.png

因為 flutter 裡使用的就是 WK,所以和原生的 WKWebView 一樣都是 444 分,比 UIWebView 的 437 略勝一籌。

結論:相容性 WKWebView = flutter_webview > UIWebView

總結

  • UIWebView: 速度相比較 WKWebView 稍快一點,但是記憶體是一大硬傷,所以只要條件允許,就不推薦使用了;
  • WKWebView: 速度略慢一點,不過差別不大,總體可以接受。是比UIWebView更好的選擇,推薦使用;
  • flutter_webView_plugin:在iOS中使用的就是原生的WKWebView,所以總體和 native WKWebView 表現差不多。如果是混編專案中,因為它被包了一層,所以頁面載入上存在一定的劣勢,所以混編專案中仍然推薦使用 WKWebView。不過如果從多端考慮、以及專案可遷移等,那麼使用也未嘗不可,就是維護成本要增加一些,需要維護兩套 webView。這個就需要根據自己的情況自己取捨了。

再讀一篇類似文章?推薦閱讀姊妹篇:

Flutter 與 Android 原生 WebView 對比


如有任何智慧財產權、版權問題或理論錯誤,還請指正。
juejin.im/post/5c778d…
本文作者 Jay,轉載請註明原作者及以上資訊。

相關文章