2. WebView 加载远程 URL 与进度反馈

WebView 加载远程 URL 与进度反馈 学习卡片

加载远程 URL 的进度反馈链路

本例在 Activity 中创建 WebView,加载一个远程页面,并用 WebChromeClient.onProgressChanged 把加载进度同步到 ProgressBar。核心对象有三个:WebView(负责请求与渲染)、WebChromeClient(回调进度与标题)、ProgressBar(可视化进度)。加载失败时通过 WebViewClient.onReceivedError 捕获错误并显示提示。

远程服务器 https://example.com HTTP GET WebView loadUrl(url) 渲染 HTML/CSS/JS settings.javaScriptEnabled = true WebChromeClient onProgressChanged(view, p) onReceivedTitle(view, t) p ∈ [0, 100] 回调 ProgressBar setProgress(p) 更新 进度 70% WebViewClient onReceivedError(view, req, err) onPageFinished(view, url) errorCode / description 失败 错误提示 Toast / 错误页 / 重试按钮 成功路径 onProgressChanged → 更新 ProgressBar → 100% 时隐藏进度条 失败路径 onReceivedError → 提示

关键实现

在 onCreate 中完成 WebView 初始化、ProgressBar 绑定和两个 Client 的设置。注意 onProgressChanged 的进度值范围是 0–100,当进度达到 100 时应隐藏进度条,避免遮挡页面内容。

public class MainActivity extends AppCompatActivity {
    private WebView webView;
    private ProgressBar progressBar;
    private static final String URL = "https://example.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);
        progressBar = findViewById(R.id.progressBar);

        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);

        // 进度回调:更新 ProgressBar
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                progressBar.setProgress(newProgress);
                if (newProgress == 100) {
                    progressBar.setVisibility(View.GONE);
                } else {
                    progressBar.setVisibility(View.VISIBLE);
                }
            }
        });

        // 错误处理:加载失败时提示
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request,
                                        WebResourceError error) {
                progressBar.setVisibility(View.GONE);
                Toast.makeText(MainActivity.this,
                        "加载失败: " + error.getDescription(),
                        Toast.LENGTH_LONG).show();
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                progressBar.setVisibility(View.GONE);
            }
        });

        webView.loadUrl(URL);
    }

    @Override
    protected void onDestroy() {
        if (webView != null) {
            webView.destroy();
        }
        super.onDestroy();
    }
}

布局文件要点

ProgressBar 使用水平样式,初始可见,覆盖在 WebView 上方或紧贴其顶部。推荐用 FrameLayout 让进度条悬浮在 WebView 之上,加载完成后自动隐藏。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="6dp"
        android:layout_gravity="top"
        android:max="100"
        android:progress="0" />
</FrameLayout>
验证要点:加载过程中观察进度条是否从 0 平滑增长到 100;加载完成后进度条应消失。若 URL 不可达(如断网或域名错误),应弹出 Toast 提示错误描述,且进度条不再显示。
常见问题:若进度条始终不更新,检查是否设置了 WebChromeClient——onProgressChanged 属于 WebChromeClient 而非 WebViewClient。若错误回调未触发,确认使用的是 onReceivedError(WebView, WebResourceRequest, WebResourceError) 新签名(API 23+),旧签名已废弃。