在实际项目开发中,我们用到WebView的场景,大多是在对接协议、第三方应用或网页时出现。对于页面加载,WebView没有自带等待效果。所以,需要我们去自定义各种带进度条的WebView,网上相关的例子也是不胜枚举,今天我们就来谈谈一条地址请求在WebView中的跳转问题:
WebView中有两个工具类负责管理网页各种行为:WebChromeClient和WebViewClient。分别通过setWebChromeClient()和setWebViewClient()来实例化。
WebChromeClient
Chrome一词表明这个类和webView的网页内容管理有关,它的成员方法帮助WebView处理Javascript的弹框、网站图标、网站title、加载进度等。最常用的方法如下:
onJsConfirm():页面选择框;
onJsAlert():页面提示框;
onJsPrompt():页面确认框;
onProgressChanged():加载进度;
当网页出现上述操作时,便会触发方法。其中onProgressChanged()方法通常用来设计成线性进度条的样式。当然这个工具类不是本次内容的主角。
WebViewClient(本次内容的主角):
就是帮助WebView处理各种通知、请求事件、记录页面加载过程的。 其中就包括URL地址,我们可以通过它来监控到地址的调用过程。
我们需要用到的相关的方法有:
- shouldOverrideUrlLoading():
- 若没有设置 WebViewClient 则由系统(Activity Manager)处理该 url,通常是使用浏览器打开或弹出浏览器选择对话框。
- 若设置 WebViewClient 且该方法返回 true ,则说明由应用的代码处理该 url,WebView 不处理,也就是程序员自己做处理。
如果返回了true,但是webview又没有去处理,webview区域会什么都不显示,一般返回true要搭配webview.loadUrl()进行 - 若设置 WebViewClient 且该方法返回 false,则说明由 WebView 处理该 url,即用 WebView 加载该 url。
直接返回flase,相当于上面的返回ture+webview.loadurl(),但是但是,还是有细微的差别,下面会提到
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//view.loadUrl(url);
//return true;
return false;
}
- onPageStarted():
通知app开始加载网页,每个页面开始都会加载此页面 - onPageFinished():
通知app页面加载完成,但是不保证网页图片完全加载完成
触发加载网页的行为主要有两种方式:
(A)点击页面,触发标签。
(B)调用WebView的loadUrl()方法、
这两种方法都会发出一条地址,区别就在于这条地址是目的地址还是重定向地址。
在(A)行为方式下:
-
如果是目的地址,那么方法的执行顺序是:
shouldOverrideUrlLoading() -> onPageStarted()-> onPageFinished()
shouldOverrideUrlLoading()由于它要提供给APP选择加载网页环境的机会,所以只要是网页上地址请求,都会获取到。 -
如果是重定向地址,在跳转到目的地址之前会进行不断的地址定位,每一次地址定位都会由以下执行顺序体现出来:
onPageStarted()->shouldOverrideUrlLoading()->onPageFinished()
我们暂且设定这种执行顺序叫:fixed position
那么一个正常的重定向地址,方法的执行顺序就是:
shouldOverrideUrlLoading()->fixed position -> … ->fixedposition ->onPageStarted()->onPageFinished()
在(B)行为下:
-
如果是目的地址,那么方法的执行顺序是:
onPageStarted()-> onPageFinished()
loadUrl()加载地址时,一般不会触发shouldOverrideUrlLoading(),一旦触发了,就说明这是一个重定向地址。 -
如果是重定向地址,方法的执行顺序就是:
fixed position -> … -> fixed position ->onPageStarted()->onPageFinished()
总结一下shouldOverrideUrlLoading
的调用时机
WebView的前进、后退、刷新、以及post请求都不会调用shouldOverrideUrlLoading方法,
除去以上行为,还得满足( ! isLoadUrl || isRedirect) 即 (不是通过webView.loadUrl来加载的 或者 是重定向) 这个条件,才会调用shouldOverrideUrlLoading方法。
- ! isLoadUrl:也就是不是通过webView.loadUrl来加载的,也就是A行为,必定会触发
- isRedirect 也就是B2,他会执行一个fixed position,就会包含这个方法,也必定会触发
shouldOverrideUrlLoading返回值
下面先做一个实验:分别返回true和false,打印日志,看有什么不同
返回true的情况
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.e("zxy", "shouldOverrideUrlLoading:::" + url);
mWebView.loadUrl(url);
return true;
}
false的情况:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.e("zxy", "shouldOverrideUrlLoading:::" + url);
// mWebView.loadUrl(url);
return false;
}
我们可以看到,true的情况下比false多了一次started()和Finished()调用,这就会造成,如果这两个方法内,有一些变量的赋值操作,就会引起bug,需要谨慎对待
以上便是shouldOverrideUrlLoading调用时机的一个详解