Replaced internal HttpResponse class by tuple

This commit is contained in:
ClemensFischer 2025-09-10 23:10:32 +02:00
parent d6faf252ee
commit ea46224c14
2 changed files with 51 additions and 70 deletions

View file

@ -49,11 +49,11 @@ namespace MapControl
{
if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)
{
var response = await GetHttpResponseAsync(uri, progress);
(var buffer, var _) = await GetHttpResponseAsync(uri, progress);
if (response?.Buffer != null)
if (buffer != null)
{
image = await LoadImageAsync(response.Buffer);
image = await LoadImageAsync(buffer);
}
}
else if (uri.IsFile || !uri.IsAbsoluteUri)
@ -75,21 +75,10 @@ namespace MapControl
return image;
}
internal class HttpResponse
internal static async Task<(byte[], TimeSpan?)> GetHttpResponseAsync(Uri uri, IProgress<double> progress = null)
{
public byte[] Buffer { get; }
public TimeSpan? MaxAge { get; }
public HttpResponse(byte[] buffer, TimeSpan? maxAge)
{
Buffer = buffer;
MaxAge = maxAge;
}
}
internal static async Task<HttpResponse> GetHttpResponseAsync(Uri uri, IProgress<double> progress = null)
{
HttpResponse response = null;
byte[] buffer = null;
TimeSpan? maxAge = null;
try
{
@ -99,8 +88,6 @@ namespace MapControl
{
if (responseMessage.IsSuccessStatusCode)
{
byte[] buffer;
if (progress != null && responseMessage.Content.Headers.ContentLength.HasValue)
{
buffer = await ReadAsByteArray(responseMessage.Content, progress).ConfigureAwait(false);
@ -110,7 +97,7 @@ namespace MapControl
buffer = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
}
response = new HttpResponse(buffer, responseMessage.Headers.CacheControl?.MaxAge);
maxAge = responseMessage.Headers.CacheControl?.MaxAge;
}
else
{
@ -127,7 +114,7 @@ namespace MapControl
Logger?.LogError(ex, "Failed loading {uri}", uri);
}
return response;
return (buffer, maxAge);
}
private static async Task<byte[]> ReadAsByteArray(HttpContent content, IProgress<double> progress)

View file

@ -138,7 +138,27 @@ namespace MapControl
try
{
await LoadTileImage(tile, tileSource, cacheName).ConfigureAwait(false);
// Pass tileSource.LoadImageAsync calls to platform-specific method
// tile.LoadImageAsync(Func<Task<ImageSource>>) for completion in the UI thread.
if (string.IsNullOrEmpty(cacheName))
{
await tile.LoadImageAsync(() => tileSource.LoadImageAsync(tile.ZoomLevel, tile.Column, tile.Row)).ConfigureAwait(false);
}
else
{
var uri = tileSource.GetUri(tile.ZoomLevel, tile.Column, tile.Row);
if (uri != null)
{
var buffer = await LoadCachedBuffer(tile, uri, cacheName).ConfigureAwait(false);
if (buffer?.Length > 0)
{
await tile.LoadImageAsync(() => tileSource.LoadImageAsync(buffer)).ConfigureAwait(false);
}
}
}
}
catch (Exception ex)
{
@ -147,31 +167,6 @@ namespace MapControl
}
}
private static async Task LoadTileImage(Tile tile, TileSource tileSource, string cacheName)
{
// Pass tileSource.LoadImageAsync calls to platform-specific method
// tile.LoadImageAsync(Func<Task<ImageSource>>) for execution on the UI thread in WinUI and UWP.
if (string.IsNullOrEmpty(cacheName))
{
await tile.LoadImageAsync(() => tileSource.LoadImageAsync(tile.ZoomLevel, tile.Column, tile.Row)).ConfigureAwait(false);
}
else
{
var uri = tileSource.GetUri(tile.ZoomLevel, tile.Column, tile.Row);
if (uri != null)
{
var buffer = await LoadCachedBuffer(tile, uri, cacheName).ConfigureAwait(false);
if (buffer?.Length > 0)
{
await tile.LoadImageAsync(() => tileSource.LoadImageAsync(buffer)).ConfigureAwait(false);
}
}
}
}
private static async Task<byte[]> LoadCachedBuffer(Tile tile, Uri uri, string cacheName)
{
var extension = Path.GetExtension(uri.LocalPath);
@ -182,42 +177,41 @@ namespace MapControl
}
var cacheKey = $"{cacheName}/{tile.ZoomLevel}/{tile.Column}/{tile.Row}{extension}";
byte[] buffer = null;
try
{
buffer = await Cache.GetAsync(cacheKey).ConfigureAwait(false);
var cachedBuffer = await Cache.GetAsync(cacheKey).ConfigureAwait(false);
if (cachedBuffer != null)
{
return cachedBuffer;
}
}
catch (Exception ex)
{
Logger?.LogError(ex, "Cache.GetAsync({cacheKey})", cacheKey);
}
if (buffer == null)
(var buffer, var maxAge) = await ImageLoader.GetHttpResponseAsync(uri).ConfigureAwait(false);
if (buffer != null)
{
var response = await ImageLoader.GetHttpResponseAsync(uri).ConfigureAwait(false);
if (response != null)
try
{
buffer = response.Buffer ?? Array.Empty<byte>(); // cache even if null, when no tile available
try
var options = new DistributedCacheEntryOptions
{
var options = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
!response.MaxAge.HasValue ? DefaultCacheExpiration
: response.MaxAge.Value < MinCacheExpiration ? MinCacheExpiration
: response.MaxAge.Value > MaxCacheExpiration ? MaxCacheExpiration
: response.MaxAge.Value
};
AbsoluteExpirationRelativeToNow =
!maxAge.HasValue ? DefaultCacheExpiration
: maxAge.Value < MinCacheExpiration ? MinCacheExpiration
: maxAge.Value > MaxCacheExpiration ? MaxCacheExpiration
: maxAge.Value
};
await Cache.SetAsync(cacheKey, buffer, options).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger?.LogError(ex, "Cache.SetAsync({cacheKey})", cacheKey);
}
await Cache.SetAsync(cacheKey, buffer, options).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger?.LogError(ex, "Cache.SetAsync({cacheKey})", cacheKey);
}
}