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<>(); HistoryRecordManager recordManager = new HistoryRecordManager(getContext());
boolean thumbnailVideoRemoved = false; Iterator<PlaylistStreamEntry> playlistIter = playlist.iterator();
Long removedItemCount = 0l; Iterator<StreamHistoryEntry> historyIter = recordManager
.getStreamHistorySortedById().blockingFirst().iterator();
HistoryRecordManager recordManager = new HistoryRecordManager(getContext()); // already sorted by ^ getStreamHistorySortedById(), binary search can be used
ArrayList<Long> historyStreamIds = new ArrayList<>();
while(historyIter.hasNext()) {
historyStreamIds.add(historyIter.next().getStreamId());
}
Iterator<PlaylistStreamEntry> it_playlist = playlist.iterator(); List<PlaylistStreamEntry> notWatchedItems = new ArrayList<>();
PlaylistStreamEntry playlist_item = null; boolean thumbnailVideoRemoved = false;
while(playlistIter.hasNext()) {
PlaylistStreamEntry playlistItem = playlistIter.next();
int indexInHistory = Collections.binarySearch(historyStreamIds, playlistItem.getStreamId());
boolean isNonDuplicate; if (indexInHistory < 0) {
notWatchedItems.add(playlistItem);
Iterator<StreamHistoryEntry> it_history = recordManager.getStreamHistory().blockingFirst().iterator(); } else if (!thumbnailVideoRemoved && playlistManager.getPlaylistThumbnail(playlistId).equals(playlistItem.getStreamEntity().getThumbnailUrl())) {
ArrayList<Long> history_streamIds = new ArrayList<>(); thumbnailVideoRemoved = true;
while(it_history.hasNext())
{
history_streamIds.add(it_history.next().getStreamId());
}
while(it_playlist.hasNext())
{
playlist_item = it_playlist.next();
isNonDuplicate = true;
for (long history_id : history_streamIds) {
if (history_id == playlist_item.getStreamId()) {
isNonDuplicate = false;
break;
}
}
if (isNonDuplicate) {
localItems.add(playlist_item);
} else {
removedItemCount++;
if (!thumbnailVideoRemoved && playlistManager.getPlaylistThumbnail(playlistId).equals(playlist_item.getStreamEntity().getThumbnailUrl())) {
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(); saveChanges();
if (thumbnailVideoRemoved)
updateThumbnailUrl();
int amountOfVideos = itemListAdapter.getItemsList().size(); if (thumbnailVideoRemoved) {
setVideoCount(amountOfVideos); updateThumbnailUrl();
}
saveChanges(); long videoCount = itemListAdapter.getItemsList().size();
hideLoading(); setVideoCount(videoCount);
if (videoCount == 0) {
showEmptyState();
}
if (amountOfVideos == 0) hideLoading();
showEmptyState(); }, this::onError
}, (@io.reactivex.annotations.NonNull Throwable throwable) -> {
onError(throwable);
}
); );
} }