android类webview,Android WebView中那些不得不处理的坑

前面那张hybrid开发心得 有人问 怎样处理不用onJsPrompt 来回调js函数的问题。其实很简单,就是在在你的jscalljava回调函数内 另外开个线程去load js代码就可:wb.post(new Runnable() { @Override public void run() { wb.loadUrl("javascript:display_alert()"); } });

好,而后开始说一下webview。webview其实我一直都很痛恨这个控件,你又不能不用,但是一旦大规模测试起来 你就发现这个webview真是坑。。。各种你想不到的错误 在各种奇怪的手机,各种不一样的版本里

出现各种难以意料的问题。再加上monkey 时不时的 帮你跑点crush,乌云平台时不时给你爆点漏洞,感觉webview天生就是在考验开发者的奇技淫巧。我自己也总结了下webview 下面的开发注意事项,现在总结出来,

希望能给你今后webview开发中 扫平少量障碍 提供少量帮助。

1.WebView的内存泄露。

关于这个问题,我很难给你一个清晰的形容,你在谷歌里搜 webview lead memory 能搜到很多结果 甚至还有给谷歌提交的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 内存泄露的问题,那么下面的方法很大程度上可以避免这种情况public void releaseAllWebViewCallback() { if (android.os.Build.VERSION.SDK_INT < 16) { try { Field field = WebView.class.getDeclaredField("mWebViewCore"); field = field.getType().getDeclaredField("mBrowserFrame"); field = field.getType().getDeclaredField("sConfigCallback"); field.setAccessible(true); field.set(null, null); } catch (NoSuchFieldException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } catch (IllegalAccessException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } } else { try { Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback"); if (sConfigCallback != null) { sConfigCallback.setAccessible(true); sConfigCallback.set(null, null); } } catch (NoSuchFieldException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } catch (ClassNotFoundException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } catch (IllegalAccessException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } } }

在webview的 destroy方法里 调用这个方法就行了。

6.另外很多人 不知道webview 实际上有自己一套完整的cookie机制的,利用好这个 可以大大添加对用户端的访问速度。

502f5d7353c775d34841e8ad8703919e.pngimage

455d7f0f3ee8c768c24abdde38c8af07.pngimage

0876126a8d92d4c507ab7bcd59ed64c9.pngimage

实际上cookie就是存放在这个表里的。

很多人都想要一个效果:网页升级cookie 设置完cookie以后 不刷新页面就可生效。这个在2.3以下和2.3以上要实现的方法不太一样,所以要做一次兼容public void updateCookies(String url, String value) { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { // 2.3及以下 CookieSyncManager.createInstance(getContext().getApplicationContext()); } CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.setCookie(url, value); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { CookieSyncManager.getInstance().sync(); } }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值