返回

WebView拦截history.back的正确姿势

Android

前言

在Android开发中,WebView作为一种轻量级的浏览器组件,广泛应用于各种移动应用中。然而,WebView对history.back方法的特殊加载流程,给拦截特定url的判断带来了不小的挑战。本文将深入分析WebView对history.back的加载机制,并提出一种基于解析栈url的解决方案,全面解析拦截history.back的正确姿势。

WebView加载流程

当WebView加载一个url时,其内部会经历如下加载流程:

  1. WebView解析url,并将请求发送给Chromium内核。
  2. Chromium内核发起网络请求,获取url对应的内容。
  3. Chromium内核将获取到的内容渲染为DOM树,并构建渲染树。
  4. WebView将渲染树显示在屏幕上。

history.back加载机制

history.back方法用于返回WebView的历史记录,加载上一页。当调用history.back时,WebView会执行以下操作:

  1. 解析当前url的栈信息,获取上一页的url。
  2. 将上一页的url放入WebView的加载队列。
  3. 加载队列中的url,并执行与正常加载流程相同的步骤。

拦截history.back的挑战

WebView对history.back的特殊加载机制,使得针对url的拦截判断变得棘手。主要原因在于:

  • 加载队列机制: WebView将上一页的url放入加载队列,即使拦截了当前页面的url,仍然无法阻止上一页的加载。
  • 栈解析不透明: WebView解析栈信息的过程对外部开发者不透明,无法直接获取上一页的url。

基于栈url解析的解决方案

为了解决上述挑战,本文提出一种基于栈url解析的解决方案:

  1. 获取WebView栈信息: 使用反射技术,获取WebView内部的栈信息。
  2. 解析栈url: 从栈信息中提取上一页的url。
  3. 拦截url: 如果解析出的url满足拦截条件,则拦截history.back操作。

实现步骤

具体实现步骤如下:

  1. 获取WebView栈信息:
Field field = WebView.class.getDeclaredField("mProvider");
field.setAccessible(true);
Provider provider = (Provider) field.get(webView);
  1. 解析栈url:
List<WebHistoryItem> historyItems = provider.getHistory();
String previousUrl = historyItems.get(historyItems.size() - 2).getUrl();
  1. 拦截url:
if (previousUrl.equals("拦截的url")) {
    webView.stopLoading();
    return true;
}

优点

基于栈url解析的解决方案具有以下优点:

  • 有效拦截: 准确解析上一页的url,并根据拦截条件进行拦截。
  • 非侵入性: 不修改WebView内部代码,避免潜在的稳定性问题。
  • 兼容性强: 适用于大多数Android版本和WebView版本。

总结

WebView拦截history.back的操作看似简单,但其特殊的加载机制给实现带来了不小的挑战。本文提出的基于栈url解析的解决方案,有效解决了这一问题。开发者可以根据本文提供的实现步骤,轻松实现WebView对history.back的拦截需求。