如何为.NET MAUI中的StreamImageSource禁用图片缓存?
.NET MAUI: 禁用StreamImageSource在Android上的Glide缓存
问题描述
使用UriImageSource时,可通过CachingEnabled = false轻松禁用图片缓存:
<Image x:Name="image"/>
var imageUri = "https://www.google.de/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"; image.Source = new UriImageSource { Uri = new Uri(imageUri), CachingEnabled = false };
但使用StreamImageSource加载图片时,尽管该类无缓存控制属性,Android平台下MAUI底层依赖的Glide库仍会将图片缓存到FileSystem.CacheDirectory/image_manager_disk_cache目录。可通过以下代码确认缓存存在:
var imageCacheDir = Path.Combine(FileSystem.CacheDirectory, "image_manager_disk_cache"); if (Directory.Exists(imageCacheDir)) { foreach (var file in Directory.EnumerateFiles(imageCacheDir)) Debug.WriteLine(file); }
示例输出:
[0:] /data/user/0/com.companyname.imagecachetest/cache/image_manager_disk_cache/journal [0:] /data/user/0/com.companyname.imagecachetest/cache/image_manager_disk_cache/5bcc99fe6930c85add40cfc486ae9a5a0451c08d71c6d3cd679ea26ec0293b9b.0
解决方案
方案1:全局禁用Glide缓存
通过自定义Glide配置,在Android项目中全局禁用磁盘和内存缓存:
- 在Android项目中创建
CustomGlideModule类:
using Android.App; using Android.Content; using Android.Glide; using Android.Glide.Modules; using Android.Glide.Request; namespace YourAppNamespace.Droid { [Application] public class CustomGlideModule : AppGlideModule { public override void ApplyOptions(Context context, GlideBuilder builder) { // 禁用磁盘缓存(设置缓存大小为0) builder.SetDiskCache(new InternalCacheDiskCacheFactory(context, 0)); // 禁用内存缓存 builder.SetMemoryCache(new LruResourceCache(0)); } } }
方案2:针对StreamImageSource单独禁用缓存
如果仅需对StreamImageSource禁用缓存,保留其他图片的缓存逻辑,可自定义ImageHandler替换默认实现:
- 在Android项目中创建自定义Handler:
using Android.Widget; using Microsoft.Maui.Handlers; using Microsoft.Maui.Platform; using Android.Graphics.Drawables; namespace YourAppNamespace.Droid { public class NoCacheImageHandler : ImageHandler { protected override ImageView CreatePlatformView() => new ImageView(Context); protected override void ConnectHandler(ImageView platformView) { base.ConnectHandler(platformView); UpdateImageSource(platformView); } private void UpdateImageSource(ImageView platformView) { if (VirtualView.Source is StreamImageSource streamSource) { // 直接加载流,绕过Glide缓存机制 _ = streamSource.Stream.Invoke(default).ContinueWith(task => { if (!task.IsFaulted && task.Result != null) { Context.RunOnUiThread(() => { using var stream = task.Result; var drawable = Drawable.CreateFromStream(stream, null); platformView.SetImageDrawable(drawable); }); } }); } else { // 其他ImageSource类型沿用默认加载逻辑 base.UpdateValue(nameof(IImage.Source)); } } protected override void DisconnectHandler(ImageView platformView) { platformView.SetImageDrawable(null); base.DisconnectHandler(platformView); } } }
- 在MAUI项目的
MauiProgram.cs中注册该Handler:
using Microsoft.Maui.Hosting; using YourAppNamespace.Droid; namespace YourAppNamespace { public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureMauiHandlers(handlers => { #if ANDROID handlers.AddHandler<Microsoft.Maui.Controls.Image, NoCacheImageHandler>(); #endif }); return builder.Build(); } } }
方案3:手动清理缓存(临时方案)
若仅需在特定场景清理缓存,可直接删除Glide缓存目录下的文件:
var imageCacheDir = Path.Combine(FileSystem.CacheDirectory, "image_manager_disk_cache"); if (Directory.Exists(imageCacheDir)) { foreach (var file in Directory.EnumerateFiles(imageCacheDir)) { try { File.Delete(file); } catch { /* 忽略删除失败的文件 */ } } }
注意:此方法会清除所有Glide缓存,适合一次性使用场景。
内容的提问来源于stack exchange,提问作者Clemens
相关产品推荐
相关产品推荐

