mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-27 20:02:01 +02:00
perf(library): reuse collection lookups across selection rebuilds
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import 'package:spotiflac_android/models/track.dart';
|
||||
import 'package:spotiflac_android/providers/download_history_provider.dart';
|
||||
import 'package:spotiflac_android/providers/library_collections_provider.dart';
|
||||
import 'package:spotiflac_android/services/history_database.dart';
|
||||
|
||||
/// Collection providers replace their track list when its contents change.
|
||||
/// Keep derived data across selection/layout rebuilds of the same snapshot.
|
||||
class LibraryTracksFolderData {
|
||||
List<CollectionTrackEntry>? _entries;
|
||||
Set<String> keys = const {};
|
||||
List<Track> tracks = const [];
|
||||
HistoryBatchLookupRequest historyRequest = const HistoryBatchLookupRequest(
|
||||
[],
|
||||
);
|
||||
|
||||
void update(List<CollectionTrackEntry> entries) {
|
||||
if (identical(entries, _entries)) return;
|
||||
_entries = entries;
|
||||
keys = Set.unmodifiable(entries.map((entry) => entry.key));
|
||||
tracks = List.unmodifiable(entries.map((entry) => entry.track));
|
||||
historyRequest = HistoryBatchLookupRequest.snapshot(
|
||||
tracks.map(historyLookupForTrack),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import 'package:spotiflac_android/utils/nav_bar_inset.dart';
|
||||
import 'package:spotiflac_android/utils/cover_art_utils.dart';
|
||||
import 'package:spotiflac_android/screens/collapsing_header_scroll_mixin.dart';
|
||||
import 'package:spotiflac_android/screens/selection_mode_mixin.dart';
|
||||
import 'package:spotiflac_android/screens/library_tracks_folder_data.dart';
|
||||
import 'package:spotiflac_android/screens/track_metadata_screen.dart';
|
||||
import 'package:spotiflac_android/widgets/selection_action_button.dart';
|
||||
import 'package:spotiflac_android/widgets/selection_bottom_bar.dart';
|
||||
@@ -67,6 +68,7 @@ class _LibraryTracksFolderScreenState
|
||||
SelectionModeMixin<LibraryTracksFolderScreen>,
|
||||
CollapsingHeaderScrollMixin<LibraryTracksFolderScreen> {
|
||||
UserPlaylistCollection? playlist;
|
||||
final _folderData = LibraryTracksFolderData();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -272,7 +274,8 @@ class _LibraryTracksFolderScreenState
|
||||
break;
|
||||
}
|
||||
|
||||
pruneSelection(entries.map((e) => e.key).toSet());
|
||||
_folderData.update(entries);
|
||||
pruneSelection(_folderData.keys);
|
||||
|
||||
final title = switch (widget.mode) {
|
||||
LibraryTracksFolderMode.wishlist => context.l10n.collectionWishlist,
|
||||
@@ -297,16 +300,10 @@ class _LibraryTracksFolderScreenState
|
||||
LibraryTracksFolderMode.playlist =>
|
||||
context.l10n.collectionPlaylistEmptySubtitle,
|
||||
};
|
||||
final folderTracks = entries
|
||||
.map((entry) => entry.track)
|
||||
.toList(growable: false);
|
||||
final historyLookups = folderTracks
|
||||
.map(historyLookupForTrack)
|
||||
.toList(growable: false);
|
||||
final folderTracks = _folderData.tracks;
|
||||
final historyLookups = _folderData.historyRequest.tracks;
|
||||
final existingHistoryKeys = ref.watch(
|
||||
downloadHistoryVisibleBatchExistsProvider(
|
||||
HistoryBatchLookupRequest(historyLookups),
|
||||
),
|
||||
downloadHistoryVisibleBatchExistsProvider(_folderData.historyRequest),
|
||||
);
|
||||
|
||||
final bottomPadding = MediaQuery.paddingOf(context).bottom;
|
||||
|
||||
@@ -48,6 +48,12 @@ class HistoryBatchLookupRequest {
|
||||
|
||||
const HistoryBatchLookupRequest(this.tracks);
|
||||
|
||||
/// An immutable request whose hash is computed only once. Use for lists
|
||||
/// retained across widget builds; the legacy constructor remains available.
|
||||
factory HistoryBatchLookupRequest.snapshot(
|
||||
Iterable<HistoryLookupRequest> tracks,
|
||||
) = _HistoryBatchLookupSnapshot;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
@@ -65,6 +71,23 @@ class HistoryBatchLookupRequest {
|
||||
int get hashCode => Object.hashAll(tracks);
|
||||
}
|
||||
|
||||
class _HistoryBatchLookupSnapshot extends HistoryBatchLookupRequest {
|
||||
_HistoryBatchLookupSnapshot(Iterable<HistoryLookupRequest> tracks)
|
||||
: super(List.unmodifiable(tracks));
|
||||
|
||||
late final int _hash = Object.hashAll(tracks);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is HistoryBatchLookupRequest &&
|
||||
hashCode == other.hashCode &&
|
||||
super == other;
|
||||
|
||||
@override
|
||||
int get hashCode => _hash;
|
||||
}
|
||||
|
||||
class HistoryDatabase {
|
||||
// The FTS table is a derived, optional index and is initialized lazily after
|
||||
// the existing schema migration. Keep this contract at v13 because the
|
||||
|
||||
Reference in New Issue
Block a user