昨天在試 Android WebView 這個元件,發現整個速度跟瀏覽器完全沒得比,包括内建瀏覽器、Chrome、Firefox、Opera …。每種瀏覽器的速度都比 WebView 快上許多 … 小蛙跟許多人一樣巴不得把 chrome 塞進 app 裡面!網路上有些人推薦 chromeview,不過有一些 bug 以及對於比較低 API 的 app 是沒辦法使用的!這篇記錄小蛙遇到 WebView 在載入網頁的時候遇到 Uncaught TypeError 錯誤的解決方法。

小蛙之前只拿 WebView 來做簡單的頁面呈現,例如:我的股票精算師的新聞頁面(讀取url)、我的郵局便利查的ATM及郵局頁面(讀取assets)、Micat發現幸福的文章頁面(讀取url)。速度感覺沒有瀏覽器快但還算是可以接受!這次小蛙測試了幾個網頁,包括:小蛙的部落格-蛙齋生活蛙齋奇摩拍賣(會自動轉成手機版) … 等網頁,結構越複雜的網頁就越慢 … 但是特別的是奇摩拍賣手機版網頁,竟然也可以慢到如此誇張 … 不怪 WebView,因為就連直接用 Chrome 開啟都要花很長的一段時間,問題出在整個頁面載入完成之後,又做了大量的 DOM 操作,像是動態選單建立,動態元件 … 等等。奇摩拍賣放進了太多功能,造成整個效能低落 … (也許是小蛙自己的感覺有問題 … )!
webview.png
上圖是奇摩拍賣手機版放入 WebView 的畫面,小小一個頁面上有著非常多功能,左上角的找商品、右上角的會員、中間上方搜尋、中間選單、中間下面拍賣品陳列;但這個頁面其實有兩個部份在 WebView 中開啟的時候發生了錯誤(紅框部份)!小蛙試了很久紅框部份應該要出現動態選單,在這邊卻遲遲未出現,造成該頁面既有功能癱瘓掉 … 下圖才是正常的頁面 (用 Chrome 開啟)
webviw2.png
找了好久找不到問題在哪邊,後來在 Logcat 中發現一行關鍵的錯誤

08-08 10:04:45.990: E/Web Console(3324): Uncaught TypeError: Cannot call method 'getItem' of null at http://l.yimg.com/tu/90e25deb72225483a6103a633c757035.js:1

當時小蛙還異想天開的以為是 WebViewClient.onReceivedError 或是 WebViewClient.onLoadResource 丟出這個令人覺得大心的錯誤,如果直接把網址貼上瀏覽器會發生錯誤,把後面的 :1 刪掉就可以正常讀取該 js,那只要在 WebViewClient.onLoadResource 讀取資源的時候,把 :1 這種造成錯誤的字元過濾掉就好了,把動作加上去之後發現,事情絕對沒有笨蛋想的那麼簡單 … 這個錯誤的拋出跟上面提到那兩個 function 一點關係都沒有 … 錯誤依然存在,跑不出來的功能依然跑不出來!
Google 一下發現有很多人都遇到這個問題,解決的方法很簡單,這個錯誤的引起是因為剛剛一開始有提到該網頁是在 DOM 載入之後才開始對 DOM 元素進行操作,這邊有提到 WebSettings.setDomStorageEnabled(boolean)

public synchronized void setDomStorageEnabled (boolean flag)
Sets whether the DOM storage API is enabled. The default value is false.

預設是不做 DOM 儲存的動作,也就是說在整個網頁載入完成之後並不把 DOM tree 儲存起來,所以導致後續對於 DOM 元素的操作,因為找不到這棵 tree 而發生錯誤,只要加上以下這行

wv.getSettings().setDomStorageEnabled(true);

問題就解決了!這次使用 WebView 來做一些東西加上整個切換成 fragment 的方式,應該會遇到不少問題!黃小蛙,加油!

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *