diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4d04e2..921eeec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,13 @@ Many thanks to my sponsors, no matter how much or how little they donated. Spons # Changelog -## [10.1.1] - 2025/02/03 +## [11.0.0-dev.2] - 2025/03/09 + +* Change `FMTCTileProvider.provideTile` arguments + Require a tile's URL & optional coordinates; instead of required coordinates and required `TileLayer` +* Fixed overly-aggressive Flutter-side tile image caching which prevented changes to `TileLayer.urlTemplate` from updating the displayed tiles + +## [10.1.1] - 2025/03/09 * Fixed bug where import operation fatally crashed on some iOS devices This appears to be an [ObjectBox issue](https://github.com/objectbox/objectbox-dart/issues/654) where streaming the results of a database query caused the crash. Instead, FMTC now uses a custom chunking system to avoid streaming and also avoid loading potentially many tiles into memory. diff --git a/example/lib/src/screens/main/map_view/components/download_progress/download_progress_masker.dart b/example/lib/src/screens/main/map_view/components/download_progress/download_progress_masker.dart index 597cc019..baad5862 100644 --- a/example/lib/src/screens/main/map_view/components/download_progress/download_progress_masker.dart +++ b/example/lib/src/screens/main/map_view/components/download_progress/download_progress_masker.dart @@ -28,7 +28,7 @@ class DownloadProgressMasker extends StatefulWidget { final int minZoom; final int maxZoom; final int tileSize; - final TileLayer child; + final Widget child; // To reset after a download, the `key` must be changed diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 9d00b756..85079493 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,7 +1,7 @@ name: fmtc_demo description: The demo app for 'flutter_map_tile_caching', showcasing its functionality and use-cases. publish_to: "none" -version: 10.1.1 +version: 11.0.0 environment: sdk: ">=3.6.0 <4.0.0" diff --git a/lib/src/providers/image_provider/image_provider.dart b/lib/src/providers/image_provider/image_provider.dart index bdad0f15..b11f48dd 100644 --- a/lib/src/providers/image_provider/image_provider.dart +++ b/lib/src/providers/image_provider/image_provider.dart @@ -10,22 +10,28 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> { /// Create a specialised [ImageProvider] that uses FMTC internals to enable /// browse caching const _FMTCImageProvider({ - required this.provider, - required this.options, + required this.networkUrl, required this.coords, + required this.provider, required this.startedLoading, required this.finishedLoadingBytes, }); - /// An instance of the [FMTCTileProvider] in use - final FMTCTileProvider provider; - - /// An instance of the [TileLayer] in use - final TileLayer options; + /// The network URL of the tile at [coords], determined by + /// [FMTCTileProvider.getTileUrl] + final String networkUrl; /// The coordinates of the tile to be fetched + /// + /// Must be set when using the image provider - acts as a key for + /// [FMTCTileProvider.tileLoadingInterceptor], and is used for some debug + /// info. Optional when [provideTile] is used directly, if + /// `tileLoadingInterceptor` functionality is not used. final TileCoordinates coords; + /// An instance of the [FMTCTileProvider] in use + final FMTCTileProvider provider; + /// Function invoked when the image starts loading (not from cache) /// /// Used with [finishedLoadingBytes] to safely dispose of the `httpClient` @@ -46,7 +52,7 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> { MultiFrameImageStreamCompleter( codec: provideTile( coords: coords, - options: options, + networkUrl: networkUrl, provider: provider, key: key, finishedLoadingBytes: finishedLoadingBytes, @@ -55,26 +61,22 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> { ).then(ImmutableBuffer.fromUint8List).then((v) => decode(v)), scale: 1, debugLabel: coords.toString(), - informationCollector: () { - final tileUrl = provider.getTileUrl(coords, options); - - return [ - DiagnosticsProperty('Stores', provider.stores), - DiagnosticsProperty('Tile coordinates', coords), - DiagnosticsProperty('Tile URL', tileUrl), - DiagnosticsProperty( - 'Tile storage-suitable UID', - provider.urlTransformer?.call(tileUrl) ?? tileUrl, - ), - ]; - }, + informationCollector: () => [ + DiagnosticsProperty('Stores', provider.stores), + DiagnosticsProperty('Tile coordinates', coords), + DiagnosticsProperty('Tile URL', networkUrl), + DiagnosticsProperty( + 'Tile storage-suitable UID', + provider.urlTransformer?.call(networkUrl) ?? networkUrl, + ), + ], ); /// {@macro fmtc.tileProvider.provideTile} static Future provideTile({ - required TileCoordinates coords, - required TileLayer options, required FMTCTileProvider provider, + required String networkUrl, + TileCoordinates? coords, Object? key, void Function()? startedLoading, void Function()? finishedLoadingBytes, @@ -92,7 +94,7 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> { scheduleMicrotask(() => PaintingBinding.instance.imageCache.evict(key)); } - if (currentTLIR != null) { + if (currentTLIR != null && coords != null) { currentTLIR.error = error; provider.tileLoadingInterceptor! @@ -121,8 +123,7 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> { final Uint8List bytes; try { bytes = await _internalTileBrowser( - coords: coords, - options: options, + networkUrl: networkUrl, provider: provider, requireValidImage: requireValidImage, currentTLIR: currentTLIR, @@ -150,6 +151,7 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> { bool operator ==(Object other) => identical(this, other) || (other is _FMTCImageProvider && + other.networkUrl == networkUrl && other.coords == coords && other.provider == provider); diff --git a/lib/src/providers/image_provider/internal_tile_browser.dart b/lib/src/providers/image_provider/internal_tile_browser.dart index 393242d2..8ff49be2 100644 --- a/lib/src/providers/image_provider/internal_tile_browser.dart +++ b/lib/src/providers/image_provider/internal_tile_browser.dart @@ -4,8 +4,7 @@ part of '../../../flutter_map_tile_caching.dart'; Future _internalTileBrowser({ - required TileCoordinates coords, - required TileLayer options, + required String networkUrl, required FMTCTileProvider provider, required bool requireValidImage, required _TLIRConstructor? currentTLIR, @@ -27,7 +26,6 @@ Future _internalTileBrowser({ } } - final networkUrl = provider.getTileUrl(coords, options); final matcherUrl = provider.urlTransformer?.call(networkUrl) ?? networkUrl; currentTLIR?.networkUrl = networkUrl; diff --git a/lib/src/providers/tile_provider/tile_provider.dart b/lib/src/providers/tile_provider/tile_provider.dart index a183fffb..4117aa5f 100644 --- a/lib/src/providers/tile_provider/tile_provider.dart +++ b/lib/src/providers/tile_provider/tile_provider.dart @@ -278,9 +278,9 @@ class FMTCTileProvider extends TileProvider { @override ImageProvider getImage(TileCoordinates coordinates, TileLayer options) => _FMTCImageProvider( - provider: this, - options: options, + networkUrl: getTileUrl(coordinates, options), coords: coordinates, + provider: this, startedLoading: () => _tilesInProgress[coordinates] = Completer(), finishedLoadingBytes: () { _tilesInProgress[coordinates]?.complete(); @@ -300,9 +300,7 @@ class FMTCTileProvider extends TileProvider { } /// {@template fmtc.tileProvider.provideTile} - /// Use FMTC's caching logic to get the bytes of the specific tile (at - /// [coords]) with the specified [TileLayer] options and [FMTCTileProvider] - /// provider + /// Use FMTC's caching logic to get the bytes of the tile at [networkUrl] /// /// > [!IMPORTANT] /// > Note that this will actuate the cache writing mechanism as if a normal @@ -321,6 +319,10 @@ class FMTCTileProvider extends TileProvider { /// /// --- /// + /// [coords] is required to enable functioning of + /// [FMTCTileProvider.tileLoadingInterceptor]. If the tile loading interceptor + /// is not in use, providing coordinates is not necessary. + /// /// [key] is used to control the [ImageCache], and should be set when in a /// context where [ImageProvider.obtainKey] is available. /// @@ -342,16 +344,16 @@ class FMTCTileProvider extends TileProvider { /// to be decoded (now or at a later time). /// {@endtemplate} Future provideTile({ - required TileCoordinates coords, - required TileLayer options, + required String networkUrl, + TileCoordinates? coords, Object? key, void Function()? startedLoading, void Function()? finishedLoadingBytes, bool requireValidImage = false, }) => _FMTCImageProvider.provideTile( + networkUrl: networkUrl, coords: coords, - options: options, provider: this, key: key, startedLoading: startedLoading, diff --git a/pubspec.yaml b/pubspec.yaml index 657345f0..05aa84dd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_map_tile_caching description: Plugin for 'flutter_map' providing advanced caching functionality, with ability to download map regions for offline use. -version: 10.1.1 +version: 11.0.0-dev.2 repository: https://github.com/JaffaKetchup/flutter_map_tile_caching issue_tracker: https://github.com/JaffaKetchup/flutter_map_tile_caching/issues diff --git a/windowsApplicationInstallerSetup.iss b/windowsApplicationInstallerSetup.iss index 3f7c58ad..a131ac3d 100644 --- a/windowsApplicationInstallerSetup.iss +++ b/windowsApplicationInstallerSetup.iss @@ -1,7 +1,7 @@ ; Script generated by the Inno Setup Script Wizard #define MyAppName "FMTC Demo" -#define MyAppVersion "for 10.1.1" +#define MyAppVersion "for 11.0.0" #define MyAppPublisher "JaffaKetchup Development" #define MyAppURL "https://github.com/JaffaKetchup/flutter_map_tile_caching" #define MyAppSupportURL "https://github.com/JaffaKetchup/flutter_map_tile_caching/issues"