uni-app 清除缓存有一定几率会导致app无响应
uni-app 清除缓存有一定几率会导致app无响应
| 类别 | 信息 |
|---|---|
| 产品分类 | uniapp/App |
| PC开发环境 | Windows |
| PC开发环境版本 | 10 |
| HBuilderX类型 | 正式 |
| HBuilderX版本 | 3.2.16 |
| 手机系统 | Android |
| 手机系统版本 | Android 9.0 |
| 手机厂商 | 华为 |
| 手机机型 | 畅享9 |
| 页面类型 | vue |
| vue版本 | vue2 |
| 打包方式 | 离线 |
| 项目创建方式 | HBuilderX |
示例代码:
// 使用plus.cache.calculate 获取应用的缓存大小,
plus.cache.calculate(function(size) {
//size是多少个字节单位是b
//你可以做下面相应的处理
if (size < 1024) {
self.xxx = size + 'B';
} else if (size / 1024 >= 1 && size / 1024 / 1024 < 1) {
self.xxx = Math.floor((size / 1024) * 100) / 100 + 'KB';
} else if (size / 1024 / 1024 >= 1) {
self.xxx = Math.floor((size / 1024 / 1024) * 100) / 100 + 'M';
} else {
self.xxx = '';
}
console.log('size是多少个字节单位是');
console.log(self.xxx);
//可以询问用户是否删除
uni.showModal({
title: '提示',
content: '确定清除缓存吗?',
success(res) {
// 用户确定要删除
if (res.confirm) {
//使用plus.cache.clear 清除应用中的缓存数据 这里清除后还要二十几KB没有清除,达不到全部清除
plus.cache.clear(function() {
uni.showToast({
// title: "成功清除" + self.xxx + '缓存',
title: '缓存清除成功',
icon: 'none',
success() {
//成功后处理
}
});
// uni.clearStorageSync();
});
}
}
});
});
操作步骤:
- 点击清除缓存
预期结果:
- 正常清除
实际结果:
- 概率弹出app 无响应
bug描述:
- 清除缓存,会有概率弹出app 无响应
更多关于uni-app 清除缓存有一定几率会导致app无响应的实战教程也可以访问 https://www.itying.com/category-93-b0.html
根据您提供的信息,这是一个典型的异步操作阻塞主线程导致的ANR(Application Not Responding)问题。在Android平台上,当主线程被阻塞超过5秒时,系统就会弹出“应用无响应”的提示。
问题分析:
-
plus.cache.calculate和plus.cache.clear是同步I/O操作:这两个API在执行时,特别是当应用缓存较大时,会进行大量的文件遍历和删除操作。这些操作默认是在当前线程(即调用它们的线程)中执行的。 -
UI线程阻塞:您的代码是在一个按钮点击事件(或类似用户交互)中触发的,这个事件回调默认运行在UI主线程。当
calculate或clear方法处理大量文件时,会长时间占用主线程,导致界面无法刷新、触摸事件无法响应,从而触发系统的ANR机制。 -
概率性出现:ANR是否触发取决于清除操作的实际耗时。如果缓存文件少、处理快(低于5秒),则不会ANR;如果文件多、存储慢(例如手机I/O繁忙时),耗时超过5秒,就会触发。这解释了问题的“概率性”。
解决方案:
核心思路是将耗时的缓存计算和清理操作放到Web Worker或异步任务中执行,避免阻塞UI线程。uni-app官方推荐使用 uni.setStorageSync 等异步API,但对于 plus.cache 这种底层操作,需要手动优化。
修改后的代码示例:
// 点击清除缓存按钮触发的方法
clearCache() {
// 1. 首先立即给出反馈,提升用户体验
uni.showLoading({
title: '正在计算缓存...',
mask: true // 防止用户重复点击
});
// 2. 使用setTimeout或Promise将calculate放入下一个事件循环,轻微解耦,但根本问题仍需解决
setTimeout(async () => {
try {
// 获取缓存大小
const cacheSize = await new Promise((resolve, reject) => {
plus.cache.calculate((size) => {
resolve(size);
});
});
// 转换大小显示格式 (您的原有逻辑)
let sizeText = '';
if (cacheSize < 1024) {
sizeText = cacheSize + 'B';
} else if (cacheSize / 1024 < 1024) {
sizeText = Math.floor((cacheSize / 1024) * 100) / 100 + 'KB';
} else {
sizeText = Math.floor((cacheSize / 1024 / 1024) * 100) / 100 + 'M';
}
uni.hideLoading(); // 关闭计算中的loading
// 3. 询问用户
uni.showModal({
title: '提示',
content: `确定清除 ${sizeText} 缓存吗?`,
success: (modalRes) => {
if (modalRes.confirm) {
// 用户确认后,再次显示Loading,并执行清除
uni.showLoading({
title: '正在清除...',
mask: true
});
// 4. 关键点:将clear操作也放入异步任务
setTimeout(() => {
plus.cache.clear(() => {
uni.hideLoading();
uni.showToast({
title: '缓存清除成功',
icon: 'success'
});
// 可选:清除本地存储的同步数据(非缓存文件)
// uni.clearStorageSync();
});
}, 100); // 短暂延迟,确保UI更新
}
}
});
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '操作失败',
icon: 'error'
});
console.error('缓存操作失败:', error);
}
}, 50);
}

