3. WebView 返回键与历史记录管理

WebView 返回键与历史记录管理 学习卡片

返回键与历史记录:先判断“能不能回”,再决定“回哪里”

WebView 自带前进/后退历史栈,但系统返回键默认只会结束当前 Activity。要让返回键优先服务于网页历史,需要在 Activity 的按键分发阶段拦截 KEYCODE_BACK,先查询 canGoBack(),再决定调用 goBack() 还是交还给系统退出。

返回键分发与 WebView 历史栈决策 用户按下返回键 KEYCODE_BACK Activity.onKeyDown 拦截并判断 canGoBack() 历史栈有前页? 是 webView.goBack() 消费按键,返回 true 否 交还系统处理 super.onKeyDown() → finish() WebView 历史栈(示例) index 0 首页 /index.html index 1 列表 /list.html index 2 详情 /detail.html ▲ 当前页(栈顶) goBack() 回退 goForward() 前进 canGoBack() → true canGoForward() → false

核心实现:重写 onKeyDown

在承载 WebView 的 Activity 中重写 onKeyDown,当按下返回键且 WebView 可回退时,调用 goBack() 并返回 true 表示事件已消费;否则调用 super.onKeyDown() 让系统执行默认退出逻辑。

public class WebViewActivity extends AppCompatActivity {

    private WebView webView;

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

        webView = findViewById(R.id.webView);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient());
        webView.loadUrl("file:///android_asset/index.html");
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (webView.canGoBack()) {
                webView.goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}
为什么用 onKeyDown 而不是 onBackPressed?
onKeyDown 在按键分发阶段更早介入,能明确区分“返回键”与其他按键;onBackPressed() 在较新 API 中已被 OnBackPressedDispatcher 取代。若项目使用 AndroidX,推荐改用 getOnBackPressedDispatcher().addCallback(),逻辑等价但兼容性更好。

历史记录状态与行为对照

canGoBack()canGoForward()返回键行为返回值
true任意webView.goBack()true(消费)
false任意super.onKeyDown() → finish()false(交还系统)

验证要点

  • 加载首页后按返回键,应直接退出 Activity,而不是白屏或停留在首页。
  • 点击页面内链接跳转到第二页后按返回键,应回到首页;再按一次才退出。
  • 连续回退到栈底后,canGoBack() 返回 false,此时返回键应触发退出。
  • 若页面通过 loadUrl 重新加载同一 URL,历史栈可能新增条目,需注意 canGoBack() 的返回值变化。
常见陷阱:在 onKeyDown 中只判断 canGoBack() 却忘记返回 true,会导致 WebView 回退后系统仍执行默认退出,出现“回退一页又立刻退出”的现象。务必在消费事件时返回 true。