如何清除 WebView 的缓存、Cookie 和历史记录?
解读
面试官抛出此题,往往不是为了让你背几行 API,而是考察:
- 对 WebView 双缓存模型(内存+磁盘)与 Cookie 持久化机制的理解深度;
- 能否区分“应用级”与“系统级”数据,避免误删全局 Cookie 导致用户在其他 App 登录态失效;
- 是否具备线上灰度与兼容意识,例如国内 ROM 对 WebView 实现差异、TargetSdk≥33 对分区存储的影响;
- 能否把“清除”动作与业务场景(退出账号、切换儿童模式、WebView 热修复)结合,给出可灰度、可回滚、可监控的完整方案。
知识点
- WebView 缓存分类
1.1 内存缓存:位于当前进程,随 Activity/Fragment 销毁而释放,无需手动清。
1.2 磁盘缓存:/data/data/包名/app_webview/ 目录下的 Cache、Code Cache、GPU Cache;WebView 自身实现为 Chromium 的 Simple Cache 或 Blockfile Cache。 - Cookie 存储
2.1 旧版:/data/data/包名/app_webview/Cookies(SQLite)。
2.2 新版:/data/data/包名/app_webview/Default/Cookies(Chromium 93+)。
2.3 系统级 CookieManager 单例,跨进程由 com.android.webview 服务托管,国内部分 ROM 会魔改路径。 - 历史记录
3.1 WebBackForwardList 仅保存在内存,进程被杀即消失;
3.2 若业务自己把访问记录持久化到本地 DB,则不在 WebView 职责范围内,需业务自己删。 - 关键 API
WebView.clearCache(true) // true 同时清磁盘
WebView.clearHistory() // 仅清内存列表
CookieManager.removeAllCookies(ValueCallback)
WebStorage.deleteAllData() // LocalStorage、IndexedDB、WebSQL
ServiceWorkerController.getInstance().clearCache() // 部分国产 ROM 需反射 - 国内合规点
工信部 164 号文要求“双清单”+“一键清除”,必须在隐私政策中明示;
小米/华为/OPPO 上架检测会扫描 /sdcard/Android/data/包名 下是否残留 webview 缓存图片,若发现直接驳回。 - 性能与灰度
清除磁盘缓存会触发 200~400 ms 文件 IO,主线程调用易丢帧;
建议放 WorkManager 后台任务,并通过 AB Test 验证对 DAU 与二次启动耗时的影响。
答案
线上稳健方案分三步:
步骤一:异步清理,避免 ANR
val wm = WorkManager.getInstance(context)
wm.enqueueUniqueWork(
"clear_webview",
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequestBuilder<ClearWebViewWorker>()
.setInitialDelay(0, TimeUnit.SECONDS)
.build()
)
步骤二:Worker 内按顺序清除
class ClearWebViewWorker(ctx: Context, params: WorkerParameters) :
CoroutineWorker(ctx, params) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
// 1. 停掉所有 WebView 实例
WebViewPool.destroyAll()
// 2. Cookie
val latch = CountDownLatch(1)
CookieManager.getInstance().apply {
removeAllCookies { latch.countDown() }
flush()
}
latch.await(5, TimeUnit.SECONDS)
// 3. 缓存与存储
WebStorage.getInstance().deleteAllData()
ServiceWorkerController.getInstance().clearCache()
// 4. 磁盘缓存
WebView(applicationContext).apply {
clearCache(true) // true 表示同时清磁盘
clearHistory()
destroy()
}
// 5. 兜底删目录,兼容国产 ROM
val webviewDir = File(applicationContext.filesDir.parentFile, "app_webview")
if (webviewDir.exists()) {
deleteRecursively(webviewDir)
}
Result.success()
}
}
步骤三:回调与埋点
Worker 返回 Result.success() 后,通过 LiveData 通知 UI 层弹出“清理成功”Toast;
同时埋点 key=webview_cache_clear,带上耗时与目录大小,供后台校验是否真正清掉。
拓展思考
- 多进程场景:若应用采用 :web 子进程加载 WebView,清除动作必须在主进程执行,否则无法删除已被子进程 mmap 的缓存文件;可通过 AIDL 回调主进程统一清理。
- 热修复与版本升级:Chromium 内核升级后缓存格式可能变化,建议在首次启动新 APK 版本时强制触发一次清理,防止旧缓存解析崩溃。
- 隐私沙盒适配:Android 13 引入 Privacy Sandbox,广告相关 WebView 数据将迁移到 SDK Runtime,未来需调用 AdServices 的 clearAdServicesData(),而非直接删文件。
- 折叠屏与多窗口:同一应用可在两块屏幕各持一个 WebView,清除时需遍历所有窗口的 WebView 实例,防止漏清。
- 国内合规脚本:上架前使用华为/小米提供的本地检测工具,命令行运行
adb shell pm clear 包名 && adb shell find /sdcard/Android/data -name "*cache*" -type f | grep 包名
确认无残留,可一次性通过隐私专项审核。