mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 13:19:44 +02:00
perf: optimize native worker snapshot writes with delta mode
Replace full-queue snapshot writes on every progress tick with a lightweight delta mode that only includes the active item. - Progress tick (1s loop) now writes item_delta with only the active item instead of serializing the entire queue - Full compact_items snapshots are reserved for important events: start, pause/resume/cancel, item boundaries, finish, and service stop/destroy - Compact items omit large static fields (item_json, track_name, artist_name) that Dart already has from queue restore - Snapshot always carries item_ids for adoption correlation - Dart-side _applyAndroidNativeWorkerSnapshot handles item_delta as a single-item fallback when items array is absent - Dart-side _tryAdoptAndroidNativeWorkerSnapshot reads item_ids as fallback when items is not present - Add deferred SAF publish: native worker writes to cache, runs all finalization locally, then publishes once to SAF at the end - Forward defer_saf_publish through DownloadRequestPayload
This commit is contained in:
1 parent
6b342aeac6
commit
cfc8e699f3
6 files changed
+364
-71
No files matched your search
@@ -4520,15 +4520,22 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
|
||||
final rawItems = snapshot['items'];
|
||||
if (rawItems is! List || rawItems.isEmpty) {
|
||||
final rawItemIds = snapshot['item_ids'];
|
||||
final snapshotIds = rawItems is List
|
||||
? rawItems
|
||||
.whereType<Map<Object?, Object?>>()
|
||||
.map((item) => item['item_id']?.toString() ?? '')
|
||||
.where((id) => id.isNotEmpty)
|
||||
.toSet()
|
||||
: rawItemIds is List
|
||||
? rawItemIds
|
||||
.map((id) => id?.toString() ?? '')
|
||||
.where((id) => id.isNotEmpty)
|
||||
.toSet()
|
||||
: <String>{};
|
||||
if (snapshotIds.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final snapshotIds = rawItems
|
||||
.whereType<Map<Object?, Object?>>()
|
||||
.map((item) => item['item_id']?.toString() ?? '')
|
||||
.where((id) => id.isNotEmpty)
|
||||
.toSet();
|
||||
if (!restoredItems.any((item) => snapshotIds.contains(item.id))) {
|
||||
return false;
|
||||
}
|
||||
@@ -4958,6 +4965,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
safFileName: safFileName ?? '',
|
||||
safOutputExt: safOutputExt,
|
||||
stageSafOutput: isSafMode,
|
||||
deferSafPublish: isSafMode,
|
||||
requiresContainerConversion:
|
||||
outputExt == '.flac' &&
|
||||
_extensionRequiresNativeContainerConversion(item.service),
|
||||
@@ -4984,13 +4992,23 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
AppSettings settings,
|
||||
) async {
|
||||
final rawItems = snapshot['items'];
|
||||
if (rawItems is! List) {
|
||||
final rawDelta = snapshot['item_delta'];
|
||||
final itemSnapshots = <Map<String, dynamic>>[];
|
||||
if (rawItems is List) {
|
||||
for (final rawItem in rawItems) {
|
||||
if (rawItem is Map) {
|
||||
itemSnapshots.add(Map<String, dynamic>.from(rawItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rawDelta is Map) {
|
||||
itemSnapshots.add(Map<String, dynamic>.from(rawDelta));
|
||||
}
|
||||
if (itemSnapshots.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final rawItem in rawItems) {
|
||||
if (rawItem is! Map) continue;
|
||||
final itemSnapshot = Map<String, dynamic>.from(rawItem);
|
||||
for (final itemSnapshot in itemSnapshots) {
|
||||
final itemId = itemSnapshot['item_id']?.toString() ?? '';
|
||||
if (itemId.isEmpty || reconciledIds.contains(itemId)) {
|
||||
continue;
|
||||
|
||||
Reference in new issue
Block a user