使用非弃用时,应为弃用和非弃用变体调用两次 shouldInterceptRequest

Posted

技术标签:

【中文标题】使用非弃用时,应为弃用和非弃用变体调用两次 shouldInterceptRequest【英文标题】:shouldInterceptRequest called twice for deprecated and non deprecated variant when using non deprecated 【发布时间】:2017-08-05 21:13:07 【问题描述】:

我有覆盖 shouldInterceptRequest 方法的 webView:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) 
    WebResourceResponse response = proxy.getWebResourceResponse(request.getUrl(), request.getMethod(), request.getRequestHeaders());
    if (response == null) 
        return super.shouldInterceptRequest(view, request);
     else 
        return response;
    


@SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) 
    WebResourceResponse response = proxy.getWebResourceResponse(Uri.parse(url), "GET", null);
    if (response == null) 
        return super.shouldInterceptRequest(view, url);
     else 
        return response;
    

问题在于 Lollipop+ 两个方法都被调用了。所以我认为我应该指定不推荐使用的版本应该只用于旧的 android 版本。与 RequiresApi 完全相反... 如果原因可以通过制作复制粘贴类并使用 if-else 根据 Android 版本选择类来解决......但这真的很难看。

更新。更新以更好地反映问题。

【问题讨论】:

@RequiresApi 注释只是一个编译时标志,用于抑制 api 级别的错误,并向调用者说明它应该在调用方法之前检查版本。它在运行时不做任何事情,因此无法与 if-else 语句相提并论。 您必须坚持使用if-else 方法,在该方法中检查 API 级别并调用适当的实现。 你的代码到底是什么?新版本的 shouldInterceptRequest 调用基类中的旧版本。如果您完全覆盖 shouldInterceptRequest(没有超级调用),则不应调用旧的,恕我直言。 @Stan,我添加了完整的代码。它调用了 super,但使用当前的实现,所以应该没问题......我还看到不推荐使用的方法不是从 super 调用,而是从这个类调用。 请参阅 Android 源代码。较新的处理程序的默认实现确实使用来自请求的字符串作为字符串调用较旧的处理程序。 【参考方案1】:

WebViewClient in Android source codes 的默认实现从较新的版本中调用已弃用的 shouldInterceptRequest 版本,将来自 request 的当前 URL 作为字符串传递:

@Deprecated
public WebResourceResponse shouldInterceptRequest(WebView view, String url)

    return null;


public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)

    return shouldInterceptRequest(view, request.getUrl().toString());

由于您从自定义 WebViewClient 实现调用默认的 Lollipop 特定处理程序(当 request 为 null 时使用 super.shouldInterceptRequest(view, request)),它反过来调用已弃用处理程序的覆盖实现。

您不应从新实现中调用 super 方法以消除不推荐的方法执行。

【讨论】:

以上是关于使用非弃用时,应为弃用和非弃用变体调用两次 shouldInterceptRequest的主要内容,如果未能解决你的问题,请参考以下文章

在 GTK3 中显示股票图标的非弃用方式是啥?

如何以非弃用方式访问 Windows 上的操纵杆?

仅当缩放高于某个值时才显示markerOptions 的优化而非弃用方式

将全局样式应用到 Shadow DOM 的正确方法

在php中沉默E_DEPRECATED

Android 平台上的 Google+ API 和 Google+ 登录弃用和停用