一、问题描述
之前项目中用到WebView,一般都是这么写的
mWebView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
mWebView.loadUrl(url);
return true;
}
})
然后是返回键的处理
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
这样基本是没问题的,直到有一天发现在一款三星Galaxy Note5手机上,无法返回上一个页面,而其他手机均正常。测试发现canGoBack()
方法一直返回false,直接调goBack()
也无法回退。
二、解决过程
1,百度该问题出现频率最高的回答是这个博客,但是这个手机是7.0系统的,而且也试了没有效果。
2,Google到一个相同问题的国外帖子,在回复中使用别人的方式如下:
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
if (request.isRedirect()) {
view.loadUrl(request.getUrl().toString());
return true;
}
return false;
}
此方法测试是有效的。
但是其中request.isRedirect()
需要api 24版本,getUrl()
需要api 21版本,而我的项目最低版本是16,所以需要加上如上的版本注解。
3,查找WebView的官方文档,原文如下:
大致意思是,在webview中打开网页,直接myWebView.setWebViewClient(new WebViewClient())
就That’s it,不需要重写shouldOverrideUrlLoading()
方法,只有你需要判断链接做其他业务的时候,才需要重新该方法写自己的逻辑。
在项目中删掉了shouldOverrideUrlLoading()
方法,果然不论是该手机还是其他手机都执行正常。
三、分析
为什么不重写shouldOverrideUrlLoading()
就正常了吗?追溯一下该方法的定义:
我们看一下注释的翻译:
当当前的WebVIEW中要加载新的URL时,给宿主应用程序一个接管控件的机会。如果没有提供WebViewClient,默认情况下,WebView将要求Activity Manager为URL选择合适的处理程序。如果提供了WebViewClient,返回true意味着宿主应用程序处理URL,而返回false意味着当前WebVIEW处理URL。
对于使用POST“方法”的请求不调用此方法。
如此就明白了
在没有设置WebViewClient情况下,将启动支持合适的程序处理链接,也就是外部浏览器。
在设置了WebViewClient的情况下,而且shouldOverrideUrlLoading()返回true,则应用程序自己处理URL,需要webView.loadUrl(url)来加载链接
在设置了WebViewClient的情况下,而且shouldOverrideUrlLoading()返回false,则当前WebView处理URL