`WebViewClient.onPageFinished()` 回調觸發時,頁面(如淘寶登錄頁)實際仍在加載中(AJAX 異步請求未完成),截圖顯示內容不全。
| 方案 | 原理 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| 固定延遲 | `Handler.postDelayed(() -> snapshot(), 2000)` | 極簡單 | 不可靠:網速慢/快導致過早/過晚;浪費時間 | 簡單演示、非關鍵路徑 |
| JS 注入監聽 | `evaluateJavascript("document.readyState", ...)` 轮詢或監聽 `load`/`networkidle` | 精確感知文檔狀態 | 需注入 JS、處理跨域、SPA 路由變化複雜 | 通用頁面、需高精度 |
| 監聽網絡空閒 | Chrome DevTools Protocol (CDP) `Network.enable` + 監聽 `requestWillBeSent`/`loadingFinished` 計數歸零 | 最準確:無進行中請求視為加載完成 | 需 Android 7.0+、WebView 開啟遠程調試、代碼較複雜 | 自動化測試、爬蟲、關鍵業務截圖 |
| 業務標記法 | 頁面加載完成後執行 `window.android.onLoaded()` (需 `@JavascriptInterface`) | 零延遲、業務語義明確 | 需修改頁面代碼、不可控第三方頁面 | 自有業務頁面、混合開發 |
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// 方案:延遲 500ms 後開始輪詢 readyState
new Handler(Looper.getMainLooper()).postDelayed(() -> {
checkReadyState(view, 0);
}, 500);
}
private void checkReadyState(WebView view, int attempt) {
if (attempt > 20) { // 最多等待 10 秒
takeSnapshot(view); // 超時強制截圖
return;
}
view.evaluateJavascript("document.readyState", value -> {
if ("complete".equals(value.replace("\"", ""))) {
takeSnapshot(view);
} else {
new Handler(Looper.getMainLooper()).postDelayed(() ->
checkReadyState(view, attempt + 1), 500);
}
});
}
private void takeSnapshot(WebView view) {
// 截圖/打印/其他操作
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
view.draw(new Canvas(bitmap));
// 保存 bitmap...
}
});
最佳回答核心:「淘寶是 ajax 異步加載的,建議你加上點延遲看看」—— 直指異步加載本質,給出工程上可行的折中方案。