Use binary search to remove watched items from playlists

This commit is contained in:
Stypox 2020-04-03 18:58:47 +02:00
parent 0ac2865b74
commit 9c3f138b8e
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
3 changed files with 49 additions and 58 deletions

View File

@ -49,6 +49,13 @@ public abstract class StreamHistoryDAO implements HistoryDAO<StreamHistoryEntity
+ " ORDER BY " + STREAM_ACCESS_DATE + " DESC") + " ORDER BY " + STREAM_ACCESS_DATE + " DESC")
public abstract Flowable<List<StreamHistoryEntry>> getHistory(); public abstract Flowable<List<StreamHistoryEntry>> getHistory();
@Query("SELECT * FROM " + STREAM_TABLE
+ " INNER JOIN " + STREAM_HISTORY_TABLE
+ " ON " + STREAM_ID + " = " + JOIN_STREAM_ID
+ " ORDER BY " + STREAM_ID + " ASC")
public abstract Flowable<List<StreamHistoryEntry>> getHistorySortedById();
@Query("SELECT * FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID @Query("SELECT * FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID
+ " = :streamId ORDER BY " + STREAM_ACCESS_DATE + " DESC LIMIT 1") + " = :streamId ORDER BY " + STREAM_ACCESS_DATE + " DESC LIMIT 1")
@Nullable @Nullable

View File

@ -120,6 +120,10 @@ public class HistoryRecordManager {
return streamHistoryTable.getHistory().subscribeOn(Schedulers.io()); return streamHistoryTable.getHistory().subscribeOn(Schedulers.io());
} }
public Flowable<List<StreamHistoryEntry>> getStreamHistorySortedById() {
return streamHistoryTable.getHistorySortedById().subscribeOn(Schedulers.io());
}
public Flowable<List<StreamStatisticsEntry>> getStreamStatistics() { public Flowable<List<StreamStatisticsEntry>> getStreamStatistics() {
return streamHistoryTable.getStatistics().subscribeOn(Schedulers.io()); return streamHistoryTable.getStatistics().subscribeOn(Schedulers.io());
} }

View File

@ -375,74 +375,54 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
removeWatchedDisposable = Flowable.just(playlistManager.getPlaylistStreams(playlistId).blockingFirst()) removeWatchedDisposable = Flowable.just(playlistManager.getPlaylistStreams(playlistId).blockingFirst())
.subscribeOn(Schedulers.newThread()) .subscribeOn(Schedulers.newThread())
.map((@NonNull List<PlaylistStreamEntry> playlist) -> { .map((@NonNull List<PlaylistStreamEntry> playlist) -> {
List<PlaylistStreamEntry> localItems = new ArrayList<>();
boolean thumbnailVideoRemoved = false;
Long removedItemCount = 0l;
HistoryRecordManager recordManager = new HistoryRecordManager(getContext()); HistoryRecordManager recordManager = new HistoryRecordManager(getContext());
Iterator<PlaylistStreamEntry> playlistIter = playlist.iterator();
Iterator<StreamHistoryEntry> historyIter = recordManager
.getStreamHistorySortedById().blockingFirst().iterator();
Iterator<PlaylistStreamEntry> it_playlist = playlist.iterator(); // already sorted by ^ getStreamHistorySortedById(), binary search can be used
PlaylistStreamEntry playlist_item = null; ArrayList<Long> historyStreamIds = new ArrayList<>();
while(historyIter.hasNext()) {
boolean isNonDuplicate; historyStreamIds.add(historyIter.next().getStreamId());
Iterator<StreamHistoryEntry> it_history = recordManager.getStreamHistory().blockingFirst().iterator();
ArrayList<Long> history_streamIds = new ArrayList<>();
while(it_history.hasNext())
{
history_streamIds.add(it_history.next().getStreamId());
} }
while(it_playlist.hasNext()) List<PlaylistStreamEntry> notWatchedItems = new ArrayList<>();
{ boolean thumbnailVideoRemoved = false;
playlist_item = it_playlist.next(); while(playlistIter.hasNext()) {
isNonDuplicate = true; PlaylistStreamEntry playlistItem = playlistIter.next();
int indexInHistory = Collections.binarySearch(historyStreamIds, playlistItem.getStreamId());
for (long history_id : history_streamIds) { if (indexInHistory < 0) {
if (history_id == playlist_item.getStreamId()) { notWatchedItems.add(playlistItem);
isNonDuplicate = false; } else if (!thumbnailVideoRemoved && playlistManager.getPlaylistThumbnail(playlistId).equals(playlistItem.getStreamEntity().getThumbnailUrl())) {
break;
}
}
if (isNonDuplicate) {
localItems.add(playlist_item);
} else {
removedItemCount++;
if (!thumbnailVideoRemoved && playlistManager.getPlaylistThumbnail(playlistId).equals(playlist_item.getStreamEntity().getThumbnailUrl())) {
thumbnailVideoRemoved = true; thumbnailVideoRemoved = true;
} }
} }
}
return Flowable.just(localItems, removedItemCount, thumbnailVideoRemoved); return Flowable.just(notWatchedItems, thumbnailVideoRemoved);
} })
)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(flow -> {
flow -> { List<PlaylistStreamEntry> notWatchedItems = (List<PlaylistStreamEntry>) flow.blockingFirst();
List<PlaylistStreamEntry> localItems = (List<PlaylistStreamEntry>) flow.blockingFirst(); boolean thumbnailVideoRemoved = (Boolean) flow.blockingLast();
Boolean thumbnailVideoRemoved = (Boolean) flow.blockingLast();
itemListAdapter.clearStreamItemList(); itemListAdapter.clearStreamItemList();
itemListAdapter.addItems(localItems); itemListAdapter.addItems(notWatchedItems);
localItems.clear();
if (thumbnailVideoRemoved)
updateThumbnailUrl();
int amountOfVideos = itemListAdapter.getItemsList().size();
setVideoCount(amountOfVideos);
saveChanges(); saveChanges();
hideLoading();
if (amountOfVideos == 0)
showEmptyState(); if (thumbnailVideoRemoved) {
}, (@io.reactivex.annotations.NonNull Throwable throwable) -> { updateThumbnailUrl();
onError(throwable);
} }
long videoCount = itemListAdapter.getItemsList().size();
setVideoCount(videoCount);
if (videoCount == 0) {
showEmptyState();
}
hideLoading();
}, this::onError
); );
} }