Skip to content
Closed
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
10 changes: 6 additions & 4 deletions lib/src/layer/tile_layer/tile_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,17 @@ class TileImage extends ChangeNotifier {
}
}

// Initiates fading in and marks this TileImage as readyToDisplay when fading
// finishes. If fading is disabled or a loading error occurred this TileImage
// becomes readyToDisplay immediately.
// Called once loading has settled, successfully or not. Initiates fading in
// and marks this TileImage as readyToDisplay when fading finishes; immediate
// if fading is disabled, or if loading failed and there is an errorImage to
// paint instead. A failure with nothing to paint never becomes
// readyToDisplay.
void _display() {
final previouslyLoaded = loadFinishedAt != null;
loadFinishedAt = DateTime.now();

if (loadError) {
_readyToDisplay = true;
_readyToDisplay = errorImage != null;
if (!_disposed) notifyListeners();
return;
}
Expand Down
60 changes: 60 additions & 0 deletions test/layer/tile_layer/tile_image_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_test/flutter_test.dart';

import '../../test_utils/test_tile_image.dart';

void main() {
Future<TileImage> loadFailingTile({ImageProvider? errorImage}) {
final loaded = Completer<void>();
final tileImage = TileImage(
coordinates: const TileCoordinates(0, 0, 0),
vsync: const _TestTickerProvider(),
imageProvider: _FailingImageProvider(),
onLoadComplete: (_) => loaded.complete(),
onLoadError: (_, __, ___) {},
tileDisplay: const TileDisplay.instantaneous(),
cancelLoading: Completer(),
errorImage: errorImage,
)..load();
return loaded.future.then((_) => tileImage);
}

test('a failed tile with no error image is not ready to display', () async {
final tileImage = await loadFailingTile();

expect(tileImage.loadError, isTrue);
expect(tileImage.readyToDisplay, isFalse);
});

test('a failed tile with an error image is ready to display', () async {
final tileImage = await loadFailingTile(errorImage: testWhiteTileImage);

expect(tileImage.loadError, isTrue);
expect(tileImage.readyToDisplay, isTrue);
});
}

class _FailingImageProvider extends ImageProvider<_FailingImageProvider> {
@override
Future<_FailingImageProvider> obtainKey(ImageConfiguration configuration) =>
SynchronousFuture(this);

@override
ImageStreamCompleter loadImage(
_FailingImageProvider key,
ImageDecoderCallback decode,
) =>
OneFrameImageStreamCompleter(Future.error(Exception('tile unavailable')));
}

class _TestTickerProvider implements TickerProvider {
const _TestTickerProvider();

@override
Ticker createTicker(TickerCallback onTick) => Ticker((_) {});
}