前言
这周在做一个需求时,需要用到WebView,但是在做的过程中,却遇到了一些问题。WebView我其实接触并不多,这次的需求里还涉及了一些JS交互之类的,所以我是边学边做,但是网上的示例和教程,往往藏着一些坑,这一次我就发现关于shouldOverrideUrlLoading这个方法,网上的说法真的是五花八门,这篇文章,我们来澄清一下shouldOverrideUrlLoading的真正用法。
正文
关于shouldOverrideUrlLoading用法的误解,主要还是集中在返回值上。
错误说法1:返回true就调用系统浏览器,返回false由WebView处理。
错误说法2:返回true当前url即使是重定向url也不会再执行,返回false由系统执行url,直到不再执行此方法。
错误说法3:WebView上的所有加载都经过这个方法。
错误说法4:这是一种广为流传的用法,在shouldOverrideUrlLoading中
@Override
public boolean shouldOverrideUrlLoading(WebViewview, String url) {
view.loadUrl(url);
return true;
}
便可以在WebView中加载该url。
那么我们来看看官方文档是怎么说的: /**
* Give the host application a chance to take over the control when a new
* url is about to be loaded in the current WebView. If WebViewClient is not
* provided, by default WebView will ask Activity Manager to choose the
* proper handler for the url. If WebViewClient is provided, return true
* means the host application handles the url, while return false means the
* current WebView handles the url.
* This method is not called for requests using the POST "method".
*
* @param view The WebView that is initiating the callback.
* @param url The url to be loaded.
* @return True if the host application wants to leave the current WebView
* and handle the url itself, otherwise return false.
* @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)
* shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.
*/
大致翻译一下:
若没有设置 WebViewClient 则由系统(Activity Manager)处理该 url,通常是使用浏览器打开或弹出浏览器选择对话框。
若设置 WebViewClient 且该方法返回 true ,则说明由应用的代码处理该 url,WebView 不处理,也就是程序员自己做处理。
若设置 WebViewClient 且该方法返回 false,则说明由 WebView 处理该 url,即用 WebView 加载该 url。
所以上面的说法1和说法2都是错误的。对于说法4,直接返回false即可达到同样的效果。
至于说法3,我在断点调试的时候就已经发现不对了,并不会每次加载都走shouldOverrideUrlLoading,但是文档里并没有说shouldOverrideUrlLoading真正的调用时机是什么,所以我继续在网上查找,终于找到一篇源码分析,得出结论:
WebView的前进、后退、刷新、以及post请求都不会调用shouldOverrideUrlLoading方法,除去以上行为,还得满足( ! isLoadUrl || isRedirect) 即 (不是通过webView.loadUrl来加载的 或者 是重定向) 这个条件,才会调用shouldOverrideUrlLoading方法。
最后再补充一个知识点,关于shouldOverrideUrlLoading 和 onPageStarted 调用的先后顺序 (在会调用shouldOverrideUrlLoading 的情况下):
当我们点击页面中的一个Link时,先调用shouldOverrideUrlLoading再调用onPageStarted。
当我们通过loadUrl的方式加载一个页面时,先调用onPageStarted再调用shouldOverrideUrlLoading。
并不是我们通常理解的onPageStarted一定在前,shouldOverrideUrlLoading 一定在后。
结语
通过这件事,让我在网上查找资料的时候更加谨慎了,因为已经不是第一次出现这种情况了。广为流传的错误答案,千篇一律的复制粘贴。这对于初学者来说,往往会造成严重的误导和困惑。所以我们在写东西的时候,也要更加慎重,不要把自己都没弄清楚的东西,当成结论发表出来,更不要不加思考的去复制粘贴别人的东西。理所应当的,本文中的结论,都是笔者在网上查资料,并且结合官方文档和源码,然后自己写程序验证过的,目的是为了让更多的初学者不被误导。当然了,人无完人,如果文中出现有误的地方,也欢迎大家指正。