diff --git a/stronglift_replacement/workout_app/lib/services/map_tile_cache.dart b/stronglift_replacement/workout_app/lib/services/map_tile_cache.dart index a5a6cdf..1dcf04c 100644 --- a/stronglift_replacement/workout_app/lib/services/map_tile_cache.dart +++ b/stronglift_replacement/workout_app/lib/services/map_tile_cache.dart @@ -37,25 +37,33 @@ TileProvider buildCachedTileProvider(String cacheDir, {Dio? dio}) => dio: dio, ); -Future? _opened; +Future? _cacheDir; -/// The shared disk-cached OSM provider; opened once per process. +/// A disk-cached OSM provider; each map gets its own. +/// +/// Only the cache directory is looked up once per process. A provider is +/// never shared: `TileLayer` disposes its provider when the map goes away +/// (a `NetworkTileProvider` closes its HTTP client then), so a shared one +/// would be dead for the second map. /// /// If the cache directory cannot be had, the map still works over the -/// network without a cache, and the reason is logged at warning level. -Future openOsmTileProvider() => _opened ??= _open(); +/// network without a cache, and the reason is logged once at warning level. +Future openOsmTileProvider() async { + final dir = await (_cacheDir ??= _resolveCacheDir()); + return dir == null ? NetworkTileProvider() : buildCachedTileProvider(dir); +} -/// Forgets the opened provider (tests only). +/// Forgets the looked-up cache directory (tests only). @visibleForTesting -void resetOsmTileProvider() => _opened = null; +void resetOsmTileProvider() => _cacheDir = null; -Future _open() async { +Future _resolveCacheDir() async { try { final dir = await getApplicationCacheDirectory(); - return buildCachedTileProvider('${dir.path}/osm_tiles'); + return '${dir.path}/osm_tiles'; } on Object catch (error) { logMapWarning('map tile cache unavailable, tiles will not persist: $error'); - return NetworkTileProvider(); + return null; } } diff --git a/stronglift_replacement/workout_app/test/services/map_tile_cache_test.dart b/stronglift_replacement/workout_app/test/services/map_tile_cache_test.dart index 9b12089..0c3ea68 100644 --- a/stronglift_replacement/workout_app/test/services/map_tile_cache_test.dart +++ b/stronglift_replacement/workout_app/test/services/map_tile_cache_test.dart @@ -32,12 +32,14 @@ void main() { expect(provider.supportsCancelLoading, isTrue); }); - test('openOsmTileProvider opens a cached provider once', () async { + test('every open is a fresh cached provider (TileLayer disposes it)', () async { final dir = installFakePathProvider(); addTearDown(() => dir.deleteSync(recursive: true)); final first = await openOsmTileProvider(); + final second = await openOsmTileProvider(); expect(first, isA()); - expect(identical(await openOsmTileProvider(), first), isTrue); + expect(second, isA()); + expect(identical(second, first), isFalse); }); test('without a cache dir: network provider and a warning', () async { @@ -47,6 +49,8 @@ void main() { provider = await openOsmTileProvider(); }); expect(provider, isA()); + // Looked up once: the second map falls back without a second warning. + expect(await openOsmTileProvider(), isA()); expect( lines.where((l) => l.contains('WARNING') && l.contains('persist')), hasLength(1),