Skip to content

[WIP] v11: adjust tile/image provider to support vector tiles plugin #182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
54 changes: 28 additions & 26 deletions lib/src/providers/image_provider/image_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -46,7 +52,7 @@ class _FMTCImageProvider extends ImageProvider<_FMTCImageProvider> {
MultiFrameImageStreamCompleter(
codec: provideTile(
coords: coords,
options: options,
networkUrl: networkUrl,
provider: provider,
key: key,
finishedLoadingBytes: finishedLoadingBytes,
Expand All @@ -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<Uint8List> provideTile({
required TileCoordinates coords,
required TileLayer options,
required FMTCTileProvider provider,
required String networkUrl,
TileCoordinates? coords,
Object? key,
void Function()? startedLoading,
void Function()? finishedLoadingBytes,
Expand All @@ -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!
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 1 addition & 3 deletions lib/src/providers/image_provider/internal_tile_browser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
part of '../../../flutter_map_tile_caching.dart';

Future<Uint8List> _internalTileBrowser({
required TileCoordinates coords,
required TileLayer options,
required String networkUrl,
required FMTCTileProvider provider,
required bool requireValidImage,
required _TLIRConstructor? currentTLIR,
Expand All @@ -27,7 +26,6 @@ Future<Uint8List> _internalTileBrowser({
}
}

final networkUrl = provider.getTileUrl(coords, options);
final matcherUrl = provider.urlTransformer?.call(networkUrl) ?? networkUrl;

currentTLIR?.networkUrl = networkUrl;
Expand Down
18 changes: 10 additions & 8 deletions lib/src/providers/tile_provider/tile_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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.
///
Expand All @@ -342,16 +344,16 @@ class FMTCTileProvider extends TileProvider {
/// to be decoded (now or at a later time).
/// {@endtemplate}
Future<Uint8List> 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,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion windowsApplicationInstallerSetup.iss
Original file line number Diff line number Diff line change
@@ -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"
Expand Down