標籤:
前面那張hybrid開發心得 有人問 怎麼解決不用onJsPrompt 來回調js函數的問題。其實很簡單,就是在在你的jscalljava回呼函數內 另外開個線程去load js代碼即可:
1 wb.post(new Runnable() {2 @Override3 public void run() {4 wb.loadUrl("javascript:display_alert()");5 }6 });
好,然後開始說一下webview。webview其實我一直都很痛恨這個控制項,你又不能不用,但是一旦大規模測試起來 你就發現這個webview真是坑。。。各種你想不到的錯誤 在各種奇怪的手機,各種不一樣的版本裡
出現各種難以預料的問題。再加上monkey 時不時的 幫你跑點crush,烏雲平台時不時給你爆點漏洞,感覺webview天生就是在考驗開發人員的奇技淫巧。我自己也總結了下webview 下面的開發注意事項,現在總結出來,
希望能給你今後webview開發中 掃平一些障礙 提供一些協助。
1.WebView的記憶體泄露。
關於這個問題,我很難給你一個清晰的描述,你在Google裡搜 webview lead memory 能搜到很多結果 甚至還有給Google提交的issue 哈哈,我也無法給出一個清晰的答案 在什麼時候 什麼版本那些手機上一定會出現記憶體泄露,
但是根據我自己的monkey結果來看,有時,webview記憶體泄露的情況還是很嚴重的,尤其是當你載入的頁面比較龐大的時候。解決方案 我查了很多也用了很多,但是都不太理想,最後看了下和qq的做法,試了一下是目前效果最好的,
就是 當你要用webview的時候,記得最好 另外單獨開一個進程 去使用webview 並且當這個 進程結束時,請手動調用System.exit(0)。
這是目前對於webview 記憶體泄露 最好的解決方案。使用此方法 所有因為webview引發的 資源無法釋放等問題 全部可以解決。
2.getSettings().setBuiltInZoomControls(true) 引發的crush。
這個方法調用以後 如果你觸控螢幕幕 彈出那個提示框還沒消失的時候 你如果activity結束了 就會報錯了。3.0以上 4.4以下很多手機會出現這種情況
所以為了規避他,我們通常是在activity的onDestroy方法裏手動的將webiew設定成 setVisibility(View.GONE)
3.onPageFinished 函數到底有用沒有?
多數開發人員都是參考的http://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url-in-android 這個上面的高票答案。
但其實根據我自己觀察,這個函數並沒有什麼卵用,有的時候是提前結束,有的時候就遲遲無法結束,你信這個函數 還不如信上帝,甚至於onProgressChanged這個函數
都比onPageFinished 要准一些。如果你的產品經理堅持你一定要實現這種功能的話,我建議你 提早結束他,否則卡在那使用者遲遲動不了 這種體驗不好。
有空的同學可以跟一下源碼,onPageFinished 在不同的核心裡 調用的時機都不一樣。說實話 我也很醉。。。這個問題 有完美解決方案的 請知會我一下。。。
4.後台無法釋放js 導致耗電。
這個可能很少有人知道,我也是被投訴過 才瞭解,在有的手機裡,你如果webview載入的html裡 有一些js 一直在執行比如動畫之類的東西,如果此刻webview 掛在了後台
這些資源是不會被釋放 使用者也無法感知。。。導致一直佔有cpu 耗電特別快,所以大家記住了,如果遇到這種情況 請在onstop和onresume裡分別把setJavaScriptEnabled();
給設定成false和true。
5.如果實在不想用開額外進程的方式解決webview 記憶體泄露的問題,那麼下面的方法很大程度上可以避免這種情況
1 public void releaseAllWebViewCallback() { 2 if (android.os.Build.VERSION.SDK_INT < 16) { 3 try { 4 Field field = WebView.class.getDeclaredField("mWebViewCore"); 5 field = field.getType().getDeclaredField("mBrowserFrame"); 6 field = field.getType().getDeclaredField("sConfigCallback"); 7 field.setAccessible(true); 8 field.set(null, null); 9 } catch (NoSuchFieldException e) {10 if (BuildConfig.DEBUG) {11 e.printStackTrace();12 }13 } catch (IllegalAccessException e) {14 if (BuildConfig.DEBUG) {15 e.printStackTrace();16 }17 }18 } else {19 try {20 Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");21 if (sConfigCallback != null) {22 sConfigCallback.setAccessible(true);23 sConfigCallback.set(null, null);24 }25 } catch (NoSuchFieldException e) {26 if (BuildConfig.DEBUG) {27 e.printStackTrace();28 }29 } catch (ClassNotFoundException e) {30 if (BuildConfig.DEBUG) {31 e.printStackTrace();32 }33 } catch (IllegalAccessException e) {34 if (BuildConfig.DEBUG) {35 e.printStackTrace();36 }37 }38 }39 }
在webview的 destroy方法裡 調用這個方法就行了。
6.另外很多人 不知道webview 實際上有自己一套完整的cookie機制的,利用好這個 可以大大增加對用戶端的訪問速度。
實際上cookie就是存放在這個表裡的。
很多人都想要一個效果:網頁更新cookie 設定完cookie以後 不重新整理頁面即可生效。這個在2.3以下和2.3以上要實現的方法不太一樣,所以要做一次相容
1 4 public void updateCookies(String url, String value) { 5 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { // 2.3及以下 6 CookieSyncManager.createInstance(getContext().getApplicationContext()); 7 } 8 CookieManager cookieManager = CookieManager.getInstance(); 9 cookieManager.setAcceptCookie(true);10 cookieManager.setCookie(url, value);11 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {12 CookieSyncManager.getInstance().sync();13 }14 }
Android WebView中那些不得不解決的坑~~