debug: glide sizing, memory cache clear

This commit is contained in:
Thibault Deckers 2025-04-02 22:30:40 +02:00
parent 022ad0334e
commit 85a1b33e83
5 changed files with 75 additions and 7 deletions

View file

@ -1,6 +1,8 @@
package deckers.thibault.aves.channel.calls package deckers.thibault.aves.channel.calls
import android.content.Context import android.content.Context
import android.os.Handler
import android.os.Looper
import androidx.core.net.toUri import androidx.core.net.toUri
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
@ -21,7 +23,8 @@ class MediaFetchObjectHandler(private val context: Context) : MethodCallHandler
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) { when (call.method) {
"getEntry" -> ioScope.launch { safe(call, result, ::getEntry) } "getEntry" -> ioScope.launch { safe(call, result, ::getEntry) }
"clearSizedThumbnailDiskCache" -> ioScope.launch { safe(call, result, ::clearSizedThumbnailDiskCache) } "clearImageDiskCache" -> ioScope.launch { safe(call, result, ::clearImageDiskCache) }
"clearImageMemoryCache" -> ioScope.launch { safe(call, result, ::clearImageMemoryCache) }
else -> result.notImplemented() else -> result.notImplemented()
} }
} }
@ -47,11 +50,18 @@ class MediaFetchObjectHandler(private val context: Context) : MethodCallHandler
}) })
} }
private fun clearSizedThumbnailDiskCache(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { private fun clearImageDiskCache(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
Glide.get(context).clearDiskCache() Glide.get(context).clearDiskCache()
result.success(null) result.success(null)
} }
private fun clearImageMemoryCache(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
Handler(Looper.getMainLooper()).post {
Glide.get(context).clearMemory()
}
result.success(null)
}
companion object { companion object {
const val CHANNEL = "deckers.thibault/aves/media_fetch_object" const val CHANNEL = "deckers.thibault/aves/media_fetch_object"
} }

View file

@ -2,6 +2,7 @@ package deckers.thibault.aves.decoder
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.text.format.Formatter
import android.util.Log import android.util.Log
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder import com.bumptech.glide.GlideBuilder
@ -10,9 +11,17 @@ import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.ImageHeaderParser import com.bumptech.glide.load.ImageHeaderParser
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPoolAdapter
import com.bumptech.glide.load.engine.bitmap_recycle.LruArrayPool
import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool
import com.bumptech.glide.load.engine.cache.DiskCache
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
import com.bumptech.glide.load.engine.cache.LruResourceCache
import com.bumptech.glide.load.engine.cache.MemorySizeCalculator
import com.bumptech.glide.load.resource.bitmap.ExifInterfaceImageHeaderParser import com.bumptech.glide.load.resource.bitmap.ExifInterfaceImageHeaderParser
import com.bumptech.glide.module.AppGlideModule import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MimeTypes import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.MimeTypes.isVideo import deckers.thibault.aves.utils.MimeTypes.isVideo
import deckers.thibault.aves.utils.StorageUtils import deckers.thibault.aves.utils.StorageUtils
@ -23,6 +32,30 @@ class AvesAppGlideModule : AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) { override fun applyOptions(context: Context, builder: GlideBuilder) {
// hide noisy warning (e.g. for images that can't be decoded) // hide noisy warning (e.g. for images that can't be decoded)
builder.setLogLevel(Log.ERROR) builder.setLogLevel(Log.ERROR)
// sizing
val memorySizeCalculator = MemorySizeCalculator.Builder(context).build()
builder.setMemorySizeCalculator(memorySizeCalculator)
val size: Int = memorySizeCalculator.bitmapPoolSize
if (size > 0) {
builder.setBitmapPool(LruBitmapPool(size.toLong()))
} else {
builder.setBitmapPool(BitmapPoolAdapter())
}
builder.setArrayPool(LruArrayPool(memorySizeCalculator.arrayPoolSizeInBytes))
builder.setMemoryCache(LruResourceCache(memorySizeCalculator.memoryCacheSize.toLong()))
val diskCacheSize = DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE
val internalCacheDiskCacheFactory = InternalCacheDiskCacheFactory(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize.toLong())
builder.setDiskCache(internalCacheDiskCacheFactory)
fun toMb(bytes: Int) = Formatter.formatFileSize(context, bytes.toLong())
Log.d(
LOG_TAG, "Glide disk cache size=${toMb(diskCacheSize)}" +
", memory cache size=${toMb(memorySizeCalculator.memoryCacheSize)}" +
", bitmap pool size=${toMb(memorySizeCalculator.bitmapPoolSize)}" +
", array pool size=${toMb(memorySizeCalculator.arrayPoolSizeInBytes)}"
)
} }
override fun registerComponents(context: Context, glide: Glide, registry: Registry) { override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
@ -34,6 +67,8 @@ class AvesAppGlideModule : AppGlideModule() {
override fun isManifestParsingEnabled(): Boolean = false override fun isManifestParsingEnabled(): Boolean = false
companion object { companion object {
private val LOG_TAG = LogUtils.createTag<AvesAppGlideModule>()
// request a fresh image with the highest quality format // request a fresh image with the highest quality format
val uncachedFullImageOptions = RequestOptions() val uncachedFullImageOptions = RequestOptions()
.format(DecodeFormat.PREFER_ARGB_8888) .format(DecodeFormat.PREFER_ARGB_8888)

View file

@ -55,7 +55,9 @@ abstract class MediaFetchService {
int? priority, int? priority,
}); });
Future<void> clearSizedThumbnailDiskCache(); Future<void> clearImageDiskCache();
Future<void> clearImageMemoryCache();
bool cancelRegion(Object taskKey); bool cancelRegion(Object taskKey);
@ -255,9 +257,18 @@ class PlatformMediaFetchService implements MediaFetchService {
} }
@override @override
Future<void> clearSizedThumbnailDiskCache() async { Future<void> clearImageDiskCache() async {
try { try {
return _platformObject.invokeMethod('clearSizedThumbnailDiskCache'); return _platformObject.invokeMethod('clearImageDiskCache');
} on PlatformException catch (e, stack) {
await reportService.recordError(e, stack);
}
}
@override
Future<void> clearImageMemoryCache() async {
try {
return _platformObject.invokeMethod('clearImageMemoryCache');
} on PlatformException catch (e, stack) { } on PlatformException catch (e, stack) {
await reportService.recordError(e, stack); await reportService.recordError(e, stack);
} }

View file

@ -88,7 +88,7 @@ class _AboutDataUsageState extends State<AboutDataUsage> with FeedbackMixin {
onPressed: () async { onPressed: () async {
await storageService.deleteTempDirectory(); await storageService.deleteTempDirectory();
await storageService.deleteExternalCache(); await storageService.deleteExternalCache();
await mediaFetchService.clearSizedThumbnailDiskCache(); await mediaFetchService.clearImageDiskCache();
imageCache.clear(); imageCache.clear();
_reload(); _reload();
setState(() {}); setState(() {});

View file

@ -87,7 +87,19 @@ class _DebugCacheSectionState extends State<DebugCacheSection> with AutomaticKee
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
ElevatedButton( ElevatedButton(
onPressed: mediaFetchService.clearSizedThumbnailDiskCache, onPressed: mediaFetchService.clearImageDiskCache,
child: const Text('Clear'),
),
],
),
Row(
children: [
const Expanded(
child: Text('Glide memory cache: ?'),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: mediaFetchService.clearImageMemoryCache,
child: const Text('Clear'), child: const Text('Clear'),
), ),
], ],