fix(player): 使用雪碧图预热首帧兜底
This commit is contained in:
1 parent
48b4e67d34
commit
70d8e0f982
13 files changed
+207
-322
No files matched your search
@@ -132,36 +132,37 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
SpriteThumbnailAxisService({
|
||||
SpriteThumbnailAssetLoader? loader,
|
||||
this.cacheTtl = spriteVttCacheTtl,
|
||||
this.spriteCacheCapacity = spriteImageCacheCapacity,
|
||||
DateTime Function()? now,
|
||||
}) : _loader = loader ?? DioSpriteThumbnailAssetLoader(),
|
||||
_now = now ?? DateTime.now;
|
||||
|
||||
final SpriteThumbnailAssetLoader _loader;
|
||||
final Duration cacheTtl;
|
||||
final int spriteCacheCapacity;
|
||||
final DateTime Function() _now;
|
||||
final Map<String, _CachedAxis> _axisCache = {};
|
||||
final Map<String, Future<SpriteThumbnailAxis>> _axisRequests = {};
|
||||
final LinkedHashMap<String, _CachedSprite> _spriteCache = LinkedHashMap();
|
||||
final Map<String, Future<_CachedSprite?>> _spriteRequests = {};
|
||||
final Set<String> _failedSprites = {};
|
||||
String? _activeAxisUrl;
|
||||
int _axisGeneration = 0;
|
||||
bool _disposed = false;
|
||||
|
||||
@visibleForTesting
|
||||
int get spriteCacheSize => _spriteCache.length;
|
||||
|
||||
@visibleForTesting
|
||||
List<String> get spriteCacheKeys => _spriteCache.keys.toList();
|
||||
List<String> get spriteCacheKeys => _spriteCache.keys
|
||||
.map((url) => Uri.tryParse(url)?.pathSegments.lastOrNull ?? url)
|
||||
.toList();
|
||||
|
||||
/// 播放器就绪时预取当前 cue 与相邻 sprite,拖动帧不触发网络或解码。
|
||||
@override
|
||||
Future<void> prepareAt(String? thumbnailsUrl, Duration position) async {
|
||||
final url = _normalizeUrl(thumbnailsUrl);
|
||||
if (_disposed || url == null) return;
|
||||
_activateAxis(url);
|
||||
final axis = await _loadAxis(url);
|
||||
if (_disposed || _activeAxisUrl != url) return;
|
||||
if (_disposed) return;
|
||||
for (final cue in _prefetchCues(axis, position)) {
|
||||
await _ensureSprite(axis, cue);
|
||||
}
|
||||
@@ -170,7 +171,7 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
@override
|
||||
bool hasAxis(String? thumbnailsUrl) {
|
||||
final url = _normalizeUrl(thumbnailsUrl);
|
||||
if (url == null || url != _activeAxisUrl) return false;
|
||||
if (url == null) return false;
|
||||
return _readAxis(url) != null;
|
||||
}
|
||||
|
||||
@@ -180,12 +181,14 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
Duration position,
|
||||
) {
|
||||
final url = _normalizeUrl(thumbnailsUrl);
|
||||
if (url == null || url != _activeAxisUrl) return null;
|
||||
if (url == null) return null;
|
||||
final axis = _readAxis(url);
|
||||
if (axis == null) return null;
|
||||
final cue = selectSpriteThumbnailCue(axis.cues, position);
|
||||
if (cue == null) return null;
|
||||
final cached = _readSprite(cue.spriteFile);
|
||||
final cached = _readSprite(
|
||||
axis.resolveSpriteUri(cue.spriteFile).toString(),
|
||||
);
|
||||
if (cached == null) return null;
|
||||
final sourceRect = _scaledSourceRect(cached, cue.sourceRect);
|
||||
if (sourceRect == null) return null;
|
||||
@@ -206,13 +209,6 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _activateAxis(String url) {
|
||||
if (_activeAxisUrl == url) return;
|
||||
_activeAxisUrl = url;
|
||||
_axisGeneration++;
|
||||
_clearSprites();
|
||||
}
|
||||
|
||||
Future<SpriteThumbnailAxis> _loadAxis(String url) {
|
||||
final cached = _readAxis(url);
|
||||
if (cached != null) return Future.value(cached);
|
||||
@@ -239,7 +235,6 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
} on SpriteThumbnailForbiddenException {
|
||||
if (_disposed) return SpriteThumbnailAxis.empty(url);
|
||||
_axisCache.remove(url);
|
||||
if (_activeAxisUrl == url) _clearSprites();
|
||||
} catch (_) {
|
||||
break;
|
||||
}
|
||||
@@ -293,23 +288,23 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
SpriteThumbnailAxis axis,
|
||||
SpriteThumbnailCue cue,
|
||||
) {
|
||||
final cached = _readSprite(cue.spriteFile);
|
||||
final spriteUrl = axis.resolveSpriteUri(cue.spriteFile).toString();
|
||||
final cached = _readSprite(spriteUrl);
|
||||
if (cached != null) return Future.value(cached);
|
||||
if (_failedSprites.contains(cue.spriteFile)) return Future.value();
|
||||
final existing = _spriteRequests[cue.spriteFile];
|
||||
if (_failedSprites.contains(spriteUrl)) return Future.value();
|
||||
final existing = _spriteRequests[spriteUrl];
|
||||
if (existing != null) return existing;
|
||||
final generation = _axisGeneration;
|
||||
final request = _loadSprite(axis, cue, generation);
|
||||
_spriteRequests[cue.spriteFile] = request;
|
||||
final request = _loadSprite(axis, cue, spriteUrl);
|
||||
_spriteRequests[spriteUrl] = request;
|
||||
return request.whenComplete(() {
|
||||
_spriteRequests.remove(cue.spriteFile);
|
||||
_spriteRequests.remove(spriteUrl);
|
||||
});
|
||||
}
|
||||
|
||||
Future<_CachedSprite?> _loadSprite(
|
||||
SpriteThumbnailAxis axis,
|
||||
SpriteThumbnailCue cue,
|
||||
int generation,
|
||||
String spriteUrl,
|
||||
) async {
|
||||
SpriteThumbnailDecodedImage? decoded;
|
||||
try {
|
||||
@@ -318,16 +313,16 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
decoded = null;
|
||||
}
|
||||
if (decoded == null) {
|
||||
_failedSprites.add(cue.spriteFile);
|
||||
_failedSprites.add(spriteUrl);
|
||||
if (!_disposed) notifyListeners();
|
||||
return null;
|
||||
}
|
||||
if (_disposed || generation != _axisGeneration) {
|
||||
if (_disposed) {
|
||||
decoded.image.dispose();
|
||||
return null;
|
||||
}
|
||||
final cached = _CachedSprite(decoded);
|
||||
_putSprite(cue.spriteFile, cached);
|
||||
_putSprite(spriteUrl, cached);
|
||||
notifyListeners();
|
||||
return cached;
|
||||
}
|
||||
@@ -342,7 +337,7 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
void _putSprite(String key, _CachedSprite value) {
|
||||
_spriteCache.remove(key)?.decoded.image.dispose();
|
||||
_spriteCache[key] = value;
|
||||
while (_spriteCache.length > spriteImageCacheCapacity) {
|
||||
while (_spriteCache.length > spriteCacheCapacity) {
|
||||
final oldest = _spriteCache.remove(_spriteCache.keys.first);
|
||||
oldest?.decoded.image.dispose();
|
||||
}
|
||||
@@ -378,8 +373,6 @@ class SpriteThumbnailAxisService extends ChangeNotifier
|
||||
}
|
||||
|
||||
void _clearAll() {
|
||||
_axisGeneration++;
|
||||
_activeAxisUrl = null;
|
||||
_axisCache.clear();
|
||||
_axisRequests.clear();
|
||||
_clearSprites();
|
||||
|
||||
Reference in new issue
Block a user