Android应用断网时WebView的onReceivedError未触发问题排查
问题分析与解决方案
核心原因
你的onReceivedError在断网时未触发,主要有以下几个常见原因:
WebView缓存机制干扰
WebView默认启用LOAD_DEFAULT缓存策略,断网时如果本地有目标页面的缓存,会直接加载缓存内容,不会触发错误回调,这是最可能的诱因。API版本兼容缺失
你仅重写了API 23+的onReceivedError(WebView, WebResourceRequest, WebResourceError),但部分场景(如低版本系统、特定子资源加载错误)仍会调用旧版的onReceivedError(WebView, int, String, String),未重写该方法会导致错误被忽略。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
相关产品推荐
相关产品推荐

