欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WebView采坑(一)

程序员文章站 2022-04-15 18:09:38
...

使用webview,你可长点心
为什么要写这篇文章,其实对于webview,说简单也简单,说困难也困难。简单在于如果你只是为了简单展示网页或者本地html的话就简单,困难在于你要实现的功能多了,那就会到处都是坑。所以写webview功能的时候你要格外细心,测试的时候要认真测试。
因为坑太多,可能有些我也记不起来(这就是不及时做笔记的下场),所以想到什么写什么,也不按什么顺序或者什么结构去列举,就想到什么列什么。

1. WebViewClient的shouldOverrideUrlLoading和onReceivedError

先从简单的开始讲。
首先如果你要自定义WebViewClient的话要注意一下这两个方法,在高版本和低版本中两个方法传的参数也不同。
(1)shouldOverrideUrlLoading

    // 高版本
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        return super.shouldOverrideUrlLoading(view, request);
    }

    // 低版本
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        return super.shouldOverrideUrlLoading(view, url);
    }

(2)onReceivedError

    // 高版本
    public boolean onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        return super.onReceivedError(view, request, error);
    }

    // 低版本
    public boolean onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        return super.onReceivedError(view, errorCode, description, failingUrl);
    }

还有shouldInterceptRequest方法也是等等,在高版本下使用String 没问题,但是在低版本下是无法找到WebResourceRequest类的,也就是会报红。
甚至不仅如此,还会出现其它的问题,所以如果要使用这两个方法的话需要多留意一点。

2. 监听加载完成

平时我们可能会在加载网页的时候等进行监听,很多监听使用的是重写WebViewClient的onPageFinished方法

    public void onPageFinished(WebView view, String url) {
       ......
    }

但是这个方法并不能很准确的判断页面加载完成,比如说webview里面展示的首页跳转到另外的Url,有时候明明还是显示着跳转时的白屏,却依然调用onPageFinished方法。
而我们可以使用WebChromeClient中重写onProgressChanged方法,

    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        if (newProgress > 70) {
            ......
        }
    }

这个方法可以监听进度,可以判断如果newProgress等于100,那就是真正的页面加载完成,但是我这是判断大于75就算是页面加载完成。为什么这样做了,因为首先newProgress的值不是+1的递增,而是没法判断,有时候+10递增,有时候+20递增。而当页面加载到70左右的时候,其实页面已经是可以显示出来了,然后再加载资源。但是如果我判断100的话,有时候其实页面是能正常显示的,但是资源有问题,导致进度到不了100反而走了失败的回调。认真想想,难道每次仅仅因为一张图片加载不出来我们就宣布这个页面加载失败吗?所以我才判断70,我不知道这样做是不是最好的方法,但是至少测试的时候对于大部分情景都是没问题的。

我认为最好的做法就是封装起来,然后自己写一套生命周期流程,再向外提供钩子。至于内部的逻辑怎么判断,我这边也不敢说我做的判断就是完美的,但是用newProgress去判断页面加载是否完成的准确性还是比较高的。

3. SSL证书问题

这个比较好办,如果出现这个问题,重写这个方法,记得把super去掉

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();
    }

4. Dialog中使用webview的坑

如果在Dialog中使用webview的过程中会因为逻辑出现一点问题。这里只是举个栗子,也可能其它地方会有类似的问题,我的意思是使用webview如果不细心的话,可能会在逻辑上出现问题。
言归正传,说说我的问题。
当我在webview跳转url的时候关闭Dialog,但是这样webview依旧会做拦截的操作,即使我在关闭时设置webview等于空也没有用,我能想到的就是写个方法去关闭webview的全部监听。

5. webview拦截不到链接

有时候你会发现webview可能拦截不到链接,shouldOverrideUrlLoading方法不被调用。这会有很多原因引起,百度就能收到。我这里就只说一种情况:
有人这样说的:第一个链接不是重定向的话就拦截不到
所以有的人会感觉到好像是第一个链接如果是加载http连接就能正常拦截到,但是加载https就拦截不到,那是因为那些http连接会重定向到https。
虽然这个说法是这样说,但我反倒是觉得就是webview不会拦截到第一个url,而重定向能拦截到是因为重定向相当于跳转url,而重定向后的就是第2个url,所以就能被拦截到。
想要链接到的办法也很简单
如果链接是你家的,可以自己手动搞个重定向,如果链接不是你家的,可以自己写个监听在loadurl之前。

6. onReceivedError的调用

这个也是一个细节需要注意。onReceivedError可能并非页面加载或者跳转url出错时才会调用,我之前调用支付宝的时候页面正常加载也会调用onReceivedError方法,这样可能就会影响到逻辑
所以需要判断调用onReceivedError时当前加载的url是不是你加载的url

这里暂时列举这些吧,因为暂时就记得这些,其实webview的坑不只这么点,之后想起来再补充