mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-14 15:10:22 +02:00
perf: incremental download queue lookup updates, async cover cleanup, and native JSON decoding on iOS
- Embed DownloadQueueLookup into DownloadQueueState; add updatedForIndices() for O(changed) incremental updates during frequent progress ticks instead of full O(n) rebuild - downloadQueueLookupProvider now reads pre-computed lookup from state directly - Replace sync file deletion in DownloadedEmbeddedCoverResolver with unawaited async cleanup to avoid blocking the main thread - Parse JSON payloads on iOS native side (parseJsonPayload) so event sinks and method channel responses return native objects, avoiding redundant Dart-side JSON decode - Use .cast<String, dynamic>() instead of Map.from() in _decodeMapResult for zero-copy map handling
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:io';
|
||||
|
||||
@@ -107,7 +108,7 @@ class DownloadedEmbeddedCoverResolver {
|
||||
_pendingPreviewValidation.remove(cleanPath);
|
||||
_failedExtract.remove(cleanPath);
|
||||
if (cached != null) {
|
||||
_cleanupTempCoverPathSync(cached.previewPath);
|
||||
_scheduleTempCoverCleanup(cached.previewPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +140,7 @@ class DownloadedEmbeddedCoverResolver {
|
||||
final oldestKey = _cache.keys.first;
|
||||
final removed = _cache.remove(oldestKey);
|
||||
if (removed != null) {
|
||||
_cleanupTempCoverPathSync(removed.previewPath);
|
||||
_scheduleTempCoverCleanup(removed.previewPath);
|
||||
}
|
||||
_pendingExtract.remove(oldestKey);
|
||||
_pendingRefresh.remove(oldestKey);
|
||||
@@ -165,7 +166,7 @@ class DownloadedEmbeddedCoverResolver {
|
||||
_failedExtract.remove(cleanPath);
|
||||
onChanged?.call();
|
||||
}
|
||||
_cleanupTempCoverPathSync(entry.previewPath);
|
||||
_scheduleTempCoverCleanup(entry.previewPath);
|
||||
}
|
||||
} finally {
|
||||
_pendingPreviewValidation.remove(cleanPath);
|
||||
@@ -203,7 +204,7 @@ class DownloadedEmbeddedCoverResolver {
|
||||
result['error'] == null && await File(outputPath).exists();
|
||||
if (!hasCover) {
|
||||
_failedExtract.add(cleanPath);
|
||||
_cleanupTempCoverPathSync(outputPath);
|
||||
_scheduleTempCoverCleanup(outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,29 +218,32 @@ class DownloadedEmbeddedCoverResolver {
|
||||
_trimCacheIfNeeded();
|
||||
|
||||
if (previous != null && previous.previewPath != outputPath) {
|
||||
_cleanupTempCoverPathSync(previous.previewPath);
|
||||
_scheduleTempCoverCleanup(previous.previewPath);
|
||||
}
|
||||
onChanged?.call();
|
||||
} catch (_) {
|
||||
_failedExtract.add(cleanPath);
|
||||
_cleanupTempCoverPathSync(outputPath);
|
||||
_scheduleTempCoverCleanup(outputPath);
|
||||
} finally {
|
||||
_pendingExtract.remove(cleanPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void _cleanupTempCoverPathSync(String? coverPath) {
|
||||
static void _scheduleTempCoverCleanup(String? coverPath) {
|
||||
unawaited(_cleanupTempCoverPath(coverPath));
|
||||
}
|
||||
|
||||
static Future<void> _cleanupTempCoverPath(String? coverPath) async {
|
||||
if (coverPath == null || coverPath.isEmpty) return;
|
||||
try {
|
||||
final file = File(coverPath);
|
||||
if (file.existsSync()) {
|
||||
file.deleteSync();
|
||||
}
|
||||
final parent = file.parent;
|
||||
if (parent.existsSync()) {
|
||||
parent.deleteSync(recursive: true);
|
||||
}
|
||||
try {
|
||||
await file.delete();
|
||||
} catch (_) {}
|
||||
try {
|
||||
await file.parent.delete(recursive: true);
|
||||
} catch (_) {}
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1181,13 +1181,13 @@ class PlatformBridge {
|
||||
|
||||
static Map<String, dynamic> _decodeMapResult(dynamic result) {
|
||||
if (result is Map) {
|
||||
return Map<String, dynamic>.from(result);
|
||||
return result.cast<String, dynamic>();
|
||||
}
|
||||
if (result is String) {
|
||||
if (result.isEmpty) return const <String, dynamic>{};
|
||||
final decoded = jsonDecode(result);
|
||||
if (decoded is Map) {
|
||||
return Map<String, dynamic>.from(decoded);
|
||||
return decoded.cast<String, dynamic>();
|
||||
}
|
||||
}
|
||||
return const <String, dynamic>{};
|
||||
|
||||
Reference in New Issue
Block a user