Flutter 與 iOS 原生 WebView 對比

享物說 2019-06-28 14:26:54 1825

原文作者:享物說
原文地址:https://juejin.im/post/5c778d86e51d4506304ee348

本文對比的是 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= 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 次測試所得到的數據:

UIWebViewWKWebViewflutter_webview_plugin
0400933843582
1285637192869
2277332583221
3277635703178
4293333863092
5267937062956
6258337073038
7314529473015
8365430383634
9325834393132
avg3066.63415.43171.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,首先看之前測試時,連續打開十次新浪的內存情況:

接著我們在看一下打開淘寶首頁的內存情況

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

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

結論:內存 WKWebView > flutter_webview > UIWebView

HTML5 兼容性對比

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

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

結論:兼容性 WKWebView = flutter_webview > UIWebView

總結

  • UIWebView: 速度相比較 WKWebView 稍快一點,但是內存是一大硬傷,所以只要條件允許,就不推薦使用了;

  • WKWebView: 速度略慢一點,不過差別不大,總體可以接受。是比UIWebView更好的選擇,推薦使用;

  • flutter_webView_plugin:在iOS中使用的就是原生的WKWebView,所以總體和 native WKWebView 表現差不多。如果是混編項目中,因為它被包了一層,所以頁面加載上存在一定的劣勢,所以混編項目中仍然推薦使用 WKWebView。不過如果從多端考慮、以及項目可遷移等,那么使用也未嘗不可,就是維護成本要增加一些,需要維護兩套 webView。這個就需要根據自己的情況自己取舍了。


广东26选5开奖结果查