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

2 回复

我试试

更多关于uni-app 清除缓存有一定几率会导致app无响应的实战教程也可以访问 https://www.itying.com/category-93-b0.html


根据您提供的信息,这是一个典型的异步操作阻塞主线程导致的ANR(Application Not Responding)问题。在Android平台上,当主线程被阻塞超过5秒时,系统就会弹出“应用无响应”的提示。

问题分析:

  1. plus.cache.calculateplus.cache.clear 是同步I/O操作:这两个API在执行时,特别是当应用缓存较大时,会进行大量的文件遍历和删除操作。这些操作默认是在当前线程(即调用它们的线程)中执行的。

  2. UI线程阻塞:您的代码是在一个按钮点击事件(或类似用户交互)中触发的,这个事件回调默认运行在UI主线程。当 calculateclear 方法处理大量文件时,会长时间占用主线程,导致界面无法刷新、触摸事件无法响应,从而触发系统的ANR机制。

  3. 概率性出现: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);
}
回到顶部