GetCacheDir()与系统清除缓存按钮的差异及缓存无法清零问题排查
解决Xamarin.Forms Android应用缓存清理残留问题及API说明
一、为什么清理后仍有20KB缓存?
这些残留缓存大概率来自你未清理的其他系统缓存目录,常见的有以下几类:
- Code Cache目录:Android 6.0(API 23)及以上版本会在此目录存放ART即时编译的缓存文件,系统会将其计入应用缓存大小。通过
Context.GetCodeCacheDir()获取该目录,需要一并删除其中所有文件和子目录。 - 多外部存储缓存目录:如果设备存在多个外部存储分区(如内置共享存储+外置SD卡),
GetExternalCacheDir()仅返回第一个外部缓存目录,而Context.GetExternalCacheDirs()会返回所有可用的外部缓存目录,这些目录下的缓存文件也会被系统统计,需要遍历清理每一个。 - WebView专属缓存:如果应用使用了WebView,它的缓存除部分存于
getCacheDir()下,还可能有独立的缓存目录,仅删除目录可能无法完全清理,需调用WebView的ClearCache(true)方法彻底清理。
另外,系统设置的缓存大小显示一般不存在bug,但存在统计延迟:删除文件后,系统需要一段时间重新扫描计算缓存大小,可等待几分钟或重启应用后再查看。
二、getCacheDir()与GetExternalCacheDir()的差异及正确用法
这两个方法均用于获取应用专属缓存目录,但核心差异在于存储位置和访问限制:
1. Context.GetCacheDir()(内部缓存目录)
- 存储路径:设备内部存储的
/data/data/你的应用包名/cache/ - 核心特点:
- 应用私有目录,其他应用无法访问,无需申请存储权限
- 设备内部存储不足时,系统会自动删除该目录文件释放空间
- 卸载应用时,该目录会被自动删除
- 适用场景:存储临时、无需长期保留的小文件,如网络请求临时缓存、图片缩略图等。
2. Context.GetExternalCacheDir()(外部缓存目录)
- 存储路径:外部存储的
/Android/data/你的应用包名/cache/(外部存储可指设备内置共享存储或外置SD卡) - 核心特点:
- Android 4.4(API 19)及以上版本无需申请
WRITE_EXTERNAL_STORAGE权限即可访问;低于API 19版本需申请权限 - 外部存储不足时,系统可能删除该目录文件,但优先级低于内部缓存
- 卸载应用时,该目录会被自动删除
- Android 4.4(API 19)及以上版本无需申请
- 适用场景:存储较大的临时文件如下载安装包、高清图片缓存等,避免占用内部存储。
三、实现与系统「清除缓存」一致效果的代码示例
在Xamarin.Forms的Android项目中,可通过依赖服务实现完整清理逻辑:
using System.IO; using Android.Content; using Xamarin.Forms; [assembly: Dependency(typeof(CacheCleaner))] namespace MyXFApp.Droid { public class CacheCleaner : ICacheCleaner { public void ClearAllCache() { var context = Android.App.Application.Context; // 清理内部缓存目录 DeleteDirectory(context.CacheDir); // 清理Code Cache目录(API 23+) if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M) { DeleteDirectory(context.CodeCacheDir); } // 清理所有外部缓存目录 var externalCacheDirs = context.GetExternalCacheDirs(); foreach (var dir in externalCacheDirs) { if (dir != null) { DeleteDirectory(dir); } } // 清理WebView缓存(若应用使用WebView) Android.Webkit.WebView.ClearCache(true); } private void DeleteDirectory(Java.IO.File directory) { if (!directory.Exists) return; foreach (var file in directory.ListFiles()) { if (file.IsDirectory) { DeleteDirectory(file); } else { file.Delete(); } } directory.Delete(); } } } // 共享项目中定义接口 public interface ICacheCleaner { void ClearAllCache(); }
在共享项目中调用清理逻辑:
DependencyService.Get<ICacheCleaner>().ClearAllCache();
内容的提问来源于stack exchange,提问作者Alexandre Mirabel
相关产品推荐
相关产品推荐

