-
-
Notifications
You must be signed in to change notification settings - Fork 897
Expand file tree
/
Copy pathbase_tile_data.dart
More file actions
102 lines (90 loc) · 3.59 KB
/
base_tile_data.dart
File metadata and controls
102 lines (90 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import 'dart:async';
import 'package:flutter_map/src/layer/modern_tile_layer/base_tile_layer.dart';
import 'package:flutter_map/src/layer/modern_tile_layer/tile_loader/tile_loader.dart';
import 'package:meta/meta.dart';
/// Data associated with a particular tile coordinate, which allows
/// bi-directional communication between the [TileLoader] and
/// [BaseTileLayer.renderer].
///
/// The tile layer's internal logic consumes this interface's fields, and can
/// also manipulate the renderer.
abstract interface class BaseTileData {
/// Should be completed when the tile is fully optically visible: the tile
/// layer will start a prune of eligible tiles, and this tile will become
/// eligible for pruning.
///
/// If the tile never becomes fully optically visible, this shouldn't usually
/// be completed.
Future<void> get triggerPrune;
/// Describes what status in the loading process this tile is in.
///
/// Implementers should keep this up-to-date. It may be a specific subtype.
TileLoadStatus get loadStatus;
/// Called when a tile is removed from the map of visible tiles passed to the
/// renderer.
///
/// This should usually be used to abort loading of the underlying resource
/// if it has not yet loaded, or release the resources held by it if already
/// loaded.
///
/// If called, then it is assumed that the tile layer's internal logic no
/// longer cares about any other field in the object.
@internal
void dispose();
}
/// Wrapper for custom-shape data as a [BaseTileData].
///
/// The data carried is usually made available asynchronously, for example as
/// the result of an I/O operation or HTTP request. Alternatively, data may be
/// available synchronously if the data is loaded from prepared memory. This
/// container supports either form of data.
class WrapperTileData<D extends Object?> implements BaseTileData {
D? _data;
/// Data resource
///
/// This may be `null` if [D] is nullable & the data is `null`. In this case,
/// use [isLoaded] to determine whether this accurately reflects the `null`
/// data. Otherwise, `null` means the data is not yet available.
D? get data => _data;
final _loadedTracker = Completer<D>.sync();
/// Completes with loaded data when the data is loaded successfully
///
/// This never completes if the data completes to an error.
@override
Future<D> get triggerPrune => _loadedTracker.future;
/// Whether [data] represents the loaded data
bool get isLoaded => _loadedTracker.isCompleted;
@internal
@override
void dispose() => _dispose?.call();
final void Function()? _dispose;
@override
TileLoadStatus get loadStatus => _loadStatus;
late TileLoadStatus _loadStatus;
/// Create a container with the specified data (or the data result of the
/// specified future)
WrapperTileData({
required FutureOr<D> data,
void Function()? dispose,
}) : _dispose = dispose {
if (data is Future<D>) {
_loadStatus = TileLoadStatus.loading(loadingStarted: DateTime.now());
data.then((data) {
_loadStatus.toSuccess(loadingFinished: DateTime.now());
_loadedTracker.complete(_data = data);
}, onError: (Object error, StackTrace? stackTrace) {
_loadStatus.toError(
loadingFinished: DateTime.now(),
exception: error,
stackTrace: stackTrace,
);
_loadedTracker.completeError(error, stackTrace);
});
} else {
final timestamp = DateTime.now();
_loadStatus = TileLoadStatus.loading(loadingStarted: timestamp)
.toSuccess(loadingFinished: timestamp);
_loadedTracker.complete(_data = data);
}
}
}