You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用断网时WebView的onReceivedError未触发问题排查

问题分析与解决方案

核心原因

你的onReceivedError在断网时未触发,主要有以下几个常见原因:

  1. WebView缓存机制干扰
    WebView默认启用LOAD_DEFAULT缓存策略,断网时如果本地有目标页面的缓存,会直接加载缓存内容,不会触发错误回调,这是最可能的诱因。

  2. API版本兼容缺失
    你仅重写了API 23+的onReceivedError(WebView, WebResourceRequest, WebResourceError),但部分场景(如低版本系统、特定子资源加载错误)仍会调用旧版的onReceivedError(WebView, int, String, String),未重写该方法会导致错误被忽略。

  3. HTTP错误未单独处理
    部分HTTP级别错误(如404、503)不会触发onReceivedError,需要通过onReceivedHttpError单独处理。


针对性修复方案

1. 调整WebView缓存策略

根据需求修改缓存模式,确保断网时不加载缓存:

WebSettings webSettings = mWebView.getSettings();
// 禁用缓存,断网时直接触发错误
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
// 若需保留缓存但优先网络,可改用:
// webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

2. 兼容旧版错误回调

添加旧版onReceivedError方法实现,覆盖更多场景:

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    Log.d(TAG, "Old onReceivedError: " + failingUrl + ", " + description);
    if (shouldShowFallbackImage(failingUrl)) {
        stopLoadingAndShowFallbackImage(view);
        checkInternetAndReconnectAfterDelay(view, mainPageUrl);
    }
    super.onReceivedError(view, errorCode, description, failingUrl);
}

3. 添加HTTP错误处理

重写onReceivedHttpError处理HTTP状态码错误:

@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
    if (request.isForMainFrame() && shouldShowFallbackImage(request.getUrl().toString())) {
        stopLoadingAndShowFallbackImage(view);
        checkInternetAndReconnectAfterDelay(view, mainPageUrl);
    }
    super.onReceivedHttpError(view, request, errorResponse);
}

4. 优化网络检测逻辑

在重试前先判断网络是否可用,减少不必要的HTTP请求:

private boolean isNetworkAvailable() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

// 修改checkInternetAndReconnectAfterDelay方法
private void checkInternetAndReconnectAfterDelay(WebView view, final String url) {
    executor.execute(() -> {
        if (!isNetworkAvailable()) {
            mainHandler.postDelayed(() -> checkInternetAndReconnectAfterDelay(view, url), 3000);
            return;
        }
        boolean isMainPageReachable = isMainPageReachable();
        if (isMainPageReachable) {
            mainHandler.post(() -> loadUrlInWebView(view, url));
        } else {
            mainHandler.postDelayed(() -> checkInternetAndReconnectAfterDelay(view, url), 3000);
        }
    });
}

额外注意事项

  • 测试前需清除WebView缓存:可通过mWebView.clearCache(true)或系统设置清除应用缓存,避免缓存干扰测试结果。
  • 若目标页面使用Service Worker,需额外处理Service Worker的缓存逻辑。

内容的提问来源于stack exchange,提问作者Duliba Ionut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:24:52