现在的位置: 首页 > 综合 > 正文

在WebView自身打开链接 — 关于WebViewClient类shouldOverrideUrlLoading的错误用法

2019年09月05日 ⁄ 综合 ⁄ 共 2592字 ⁄ 字号 评论关闭

本文用来记述我所遇到的一个小问题,问题很小,显得描述有些啰嗦,只是为了叙述自己的经历而已。

前言

作为一个Android新手,几乎所有我所遇到的问题都是通过网络途径解决的,比如这次。

我所参与的一个小项目有个需求就是使用 WebView 加载一个论坛,那么论坛页面上的链接跳转就需要限制在WebView中,而不是使用默认的浏览器应用打开;而默认情况下,Android 系统会启动一个应用来处理被点击的链接,一般情况下默认浏览器会被启动来加载目标URL(或弹出浏览器选择菜单)。

关于这个问题,网络上有很多博客都介绍到了,就是采用覆盖 WebViewClient 类的 shouldOverrideUrlLoading 方法来实现。

如以下几个链接内容所述:

其实就是通过以下两段代码来实现:

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new MyWebViewClient());

自定义 WebViewClient 实现,覆盖 shouldOverrideUrlLoading 方法:

private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }

于是我也就采用了这种方式,而它确实可以解决我的问题。

问题

但今天我在阅读官方文档时却发现上面所说的解决方式其实是不正确的,至少是没有理解 API 的正确用法,官方文档在这里:

http://developer.android.com/guide/webapps/webview.html

其中有一段话引起了我的注意,在这里截图说明,如果想看原始内容,请点开上面的链接找到 shouldOverrideUrlLoading 部分,或者直接猛击这里:http://developer.android.com/guide/webapps/webview.html#HandlingNavigation

注意上图中最后一句话,意思是说这样就可以了,并不需要覆盖 shouldOverrideUrlLoading 方法,同样可以实现所有的链接都在 WebView 中打开。这样就跟网络上描述的解决方式有冲突了,虽然使用的方式是一样的,但毕竟还是有出入的。于是我觉得应该深入了解一下 WebViewClient 这个类,至少让自己明白这是怎么回事。

答案

于是我找到了 WebViewClient 的 API 文档和源码,想看看 shouldOverrideUrlLoading 方法的介绍以及实现,其中源码如下所示:

/**
     * 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.
     */
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        return false;
    }

仔细阅读注释部分,可以得知在一个新的链接即将被加载时,会出现以下几种情况:

  1. 如果没有提供 WebViewClient 对象,则 WebView 会请求 Activity 管理者选择合适的 URL 处理方式,一般情况就是启动浏览器来加载URL;
  2. 如果提供了 WebViewClient 对象且shouldOverrideUrlLoading 方法返回 true,则主机应用(意思应该是 Android 系统)处理URL;
  3. 如果提供了 WebViewClient 对象且shouldOverrideUrlLoading 方法返回 false,则当前 WebView 处理URL;

再结合 shouldOverrideUrlLoading 方法源码就可以得出上面图片中的结论,其实我们没必要自定义 WebViewClient 并重写其 shouldOverrideUrlLoading 方法,因为 WebViewClient 源码中 shouldOverrideUrlLoading 方法已经返回 false,也就是说只要你设置了 WebViewClient 就可以实现在WebView 中加载新的链接而不去调用浏览器加载。

另外文档上还有一段话,截图如下:

也就是说我们需要针对点击事件添加额外控制时才需要自定义 WebViewClient 实现,如果仅需要控制在 WebView 内加载新的 URL 只需要按上面描述的做就可以了,也就是只需要下面一段代码即可:

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());

抱歉!评论已关闭.