Add lazy loading to feed item list (#7091)
This commit is contained in:
parent
04fab47072
commit
f3bca9d9e4
|
@ -98,7 +98,7 @@ public class DownloadLogAdapter extends BaseAdapter {
|
|||
if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
|
||||
holder.secondaryActionButton.setOnClickListener(v -> {
|
||||
holder.secondaryActionButton.setVisibility(View.INVISIBLE);
|
||||
Feed feed = DBReader.getFeed(status.getFeedfileId());
|
||||
Feed feed = DBReader.getFeed(status.getFeedfileId(), false, 0, 0);
|
||||
if (feed == null) {
|
||||
Log.e(TAG, "Could not find feed for feed id: " + status.getFeedfileId());
|
||||
return;
|
||||
|
|
|
@ -28,7 +28,7 @@ public class DownloadLogDetailsDialog extends MaterialAlertDialogBuilder {
|
|||
url = media.getDownloadUrl();
|
||||
}
|
||||
} else if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
|
||||
Feed feed = DBReader.getFeed(status.getFeedfileId());
|
||||
Feed feed = DBReader.getFeed(status.getFeedfileId(), false, 0, 0);
|
||||
if (feed != null) {
|
||||
url = feed.getDownloadUrl();
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
|
|||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
long feedId = getArguments().getLong(EXTRA_FEED_ID);
|
||||
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
|
||||
Feed feed = DBReader.getFeed(feedId);
|
||||
Feed feed = DBReader.getFeed(feedId, false, 0, 0);
|
||||
if (feed != null) {
|
||||
emitter.onSuccess(feed);
|
||||
} else {
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.widget.Toast;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
@ -49,7 +50,6 @@ import de.danoeh.antennapod.event.FeedEvent;
|
|||
import de.danoeh.antennapod.ui.MenuItemUtils;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.storage.database.FeedItemPermutors;
|
||||
import de.danoeh.antennapod.ui.common.IntentUtils;
|
||||
import de.danoeh.antennapod.ui.share.ShareUtils;
|
||||
import de.danoeh.antennapod.ui.episodeslist.MoreContentListFooterUtil;
|
||||
|
@ -73,7 +73,6 @@ import de.danoeh.antennapod.model.download.DownloadResult;
|
|||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
|
||||
import de.danoeh.antennapod.ui.episodeslist.EpisodeItemViewHolder;
|
||||
|
@ -91,6 +90,10 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
|||
public static final String TAG = "ItemlistFragment";
|
||||
private static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id";
|
||||
private static final String KEY_UP_ARROW = "up_arrow";
|
||||
protected static final int EPISODES_PER_PAGE = 150;
|
||||
protected int page = 1;
|
||||
protected boolean isLoadingMore = false;
|
||||
protected boolean hasMoreItems = false;
|
||||
|
||||
private FeedItemListAdapter adapter;
|
||||
private SwipeActions swipeActions;
|
||||
|
@ -147,6 +150,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
|||
}
|
||||
((MainActivity) getActivity()).setupToolbarToggle(viewBinding.toolbar, displayUpArrow);
|
||||
updateToolbar();
|
||||
setupLoadMoreScrollListener();
|
||||
|
||||
viewBinding.recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
|
||||
adapter = new FeedItemListAdapter((MainActivity) getActivity());
|
||||
|
@ -317,6 +321,21 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
|||
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
||||
}
|
||||
|
||||
private void setupLoadMoreScrollListener() {
|
||||
viewBinding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView view, int deltaX, int deltaY) {
|
||||
super.onScrolled(view, deltaX, deltaY);
|
||||
if (!isLoadingMore && hasMoreItems && viewBinding.recyclerView.isScrolledToBottom()) {
|
||||
/* The end of the list has been reached. Load more data. */
|
||||
page++;
|
||||
loadMoreItems();
|
||||
isLoadingMore = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
MainActivity activity = (MainActivity) getActivity();
|
||||
|
@ -535,17 +554,23 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
|||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
disposable = Observable.fromCallable(this::loadData)
|
||||
disposable = Observable.fromCallable(
|
||||
() -> {
|
||||
feed = DBReader.getFeed(feedID, true, 0, page * EPISODES_PER_PAGE);
|
||||
int count = DBReader.getFeedEpisodeCount(feed.getId(), feed.getItemFilter());
|
||||
return new Pair<>(feed, count);
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
result -> {
|
||||
feed = result;
|
||||
hasMoreItems = !(page == 1 && feed.getItems().size() < EPISODES_PER_PAGE);
|
||||
swipeActions.setFilter(feed.getItemFilter());
|
||||
refreshHeaderView();
|
||||
viewBinding.progressBar.setVisibility(View.GONE);
|
||||
adapter.setDummyViews(0);
|
||||
adapter.updateItems(feed.getItems());
|
||||
adapter.setTotalNumberOfItems(result.second);
|
||||
updateToolbar();
|
||||
}, error -> {
|
||||
feed = null;
|
||||
|
@ -557,19 +582,37 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
|||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Feed loadData() {
|
||||
Feed feed = DBReader.getFeed(feedID, true);
|
||||
if (feed == null) {
|
||||
return null;
|
||||
private void loadMoreItems() {
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
DBReader.loadAdditionalFeedItemListData(feed.getItems());
|
||||
if (feed.getSortOrder() != null) {
|
||||
List<FeedItem> feedItems = feed.getItems();
|
||||
FeedItemPermutors.getPermutor(feed.getSortOrder()).reorder(feedItems);
|
||||
feed.setItems(feedItems);
|
||||
isLoadingMore = true;
|
||||
adapter.setDummyViews(1);
|
||||
adapter.notifyItemInserted(adapter.getItemCount() - 1);
|
||||
disposable = Observable.fromCallable(() -> DBReader.getFeed(feedID, true,
|
||||
(page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> {
|
||||
if (data.getItems().size() < EPISODES_PER_PAGE) {
|
||||
hasMoreItems = false;
|
||||
}
|
||||
return feed;
|
||||
feed.getItems().addAll(data.getItems());
|
||||
adapter.setDummyViews(0);
|
||||
adapter.updateItems(feed.getItems());
|
||||
if (adapter.shouldSelectLazyLoadedItems()) {
|
||||
adapter.setSelected(feed.getItems().size() - data.getItems().size(),
|
||||
feed.getItems().size(), true);
|
||||
}
|
||||
}, error -> {
|
||||
adapter.setDummyViews(0);
|
||||
adapter.updateItems(Collections.emptyList());
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
}, () -> {
|
||||
// Make sure to not always load 2 pages at once
|
||||
viewBinding.recyclerView.post(() -> isLoadingMore = false);
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
|
@ -608,45 +651,4 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
|||
MenuItemUtils.setOnClickListeners(menu, FeedItemlistFragment.this::onContextItemSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SingleFeedSortDialog extends ItemSortDialog {
|
||||
private static final String ARG_FEED_ID = "feedId";
|
||||
private static final String ARG_FEED_IS_LOCAL = "isLocal";
|
||||
private static final String ARG_SORT_ORDER = "sortOrder";
|
||||
|
||||
private static SingleFeedSortDialog newInstance(Feed feed) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(ARG_FEED_ID, feed.getId());
|
||||
bundle.putBoolean(ARG_FEED_IS_LOCAL, feed.isLocalFeed());
|
||||
if (feed.getSortOrder() == null) {
|
||||
bundle.putString(ARG_SORT_ORDER, String.valueOf(SortOrder.DATE_NEW_OLD.code));
|
||||
} else {
|
||||
bundle.putString(ARG_SORT_ORDER, String.valueOf(feed.getSortOrder().code));
|
||||
}
|
||||
SingleFeedSortDialog dialog = new SingleFeedSortDialog();
|
||||
dialog.setArguments(bundle);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
sortOrder = SortOrder.fromCodeString(getArguments().getString(ARG_SORT_ORDER));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
|
||||
if (ascending == SortOrder.DATE_OLD_NEW || ascending == SortOrder.DURATION_SHORT_LONG
|
||||
|| ascending == SortOrder.EPISODE_TITLE_A_Z
|
||||
|| (getArguments().getBoolean(ARG_FEED_IS_LOCAL) && ascending == SortOrder.EPISODE_FILENAME_A_Z)) {
|
||||
super.onAddItem(title, ascending, descending, ascendingIsDefault);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged() {
|
||||
super.onSelectionChanged();
|
||||
DBWriter.setFeedItemSortOrder(getArguments().getLong(ARG_FEED_ID), sortOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package de.danoeh.antennapod.ui.screen.feed;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.Nullable;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
|
||||
public class SingleFeedSortDialog extends ItemSortDialog {
|
||||
private static final String ARG_FEED_ID = "feedId";
|
||||
private static final String ARG_FEED_IS_LOCAL = "isLocal";
|
||||
private static final String ARG_SORT_ORDER = "sortOrder";
|
||||
|
||||
public static SingleFeedSortDialog newInstance(Feed feed) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(ARG_FEED_ID, feed.getId());
|
||||
bundle.putBoolean(ARG_FEED_IS_LOCAL, feed.isLocalFeed());
|
||||
if (feed.getSortOrder() == null) {
|
||||
bundle.putString(ARG_SORT_ORDER, String.valueOf(SortOrder.DATE_NEW_OLD.code));
|
||||
} else {
|
||||
bundle.putString(ARG_SORT_ORDER, String.valueOf(feed.getSortOrder().code));
|
||||
}
|
||||
SingleFeedSortDialog dialog = new SingleFeedSortDialog();
|
||||
dialog.setArguments(bundle);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
sortOrder = SortOrder.fromCodeString(getArguments().getString(ARG_SORT_ORDER));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAddItem(int title, SortOrder ascending, SortOrder descending, boolean ascendingIsDefault) {
|
||||
if (ascending == SortOrder.DATE_OLD_NEW || ascending == SortOrder.DURATION_SHORT_LONG
|
||||
|| ascending == SortOrder.EPISODE_TITLE_A_Z
|
||||
|| (getArguments().getBoolean(ARG_FEED_IS_LOCAL) && ascending == SortOrder.EPISODE_FILENAME_A_Z)) {
|
||||
super.onAddItem(title, ascending, descending, ascendingIsDefault);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged() {
|
||||
super.onSelectionChanged();
|
||||
DBWriter.setFeedItemSortOrder(getArguments().getLong(ARG_FEED_ID), sortOrder);
|
||||
}
|
||||
}
|
|
@ -81,7 +81,7 @@ public class FeedSettingsFragment extends Fragment {
|
|||
.commitAllowingStateLoss();
|
||||
|
||||
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
|
||||
Feed feed = DBReader.getFeed(feedId);
|
||||
Feed feed = DBReader.getFeed(feedId, false, 0, 0);
|
||||
if (feed != null) {
|
||||
emitter.onSuccess(feed);
|
||||
} else {
|
||||
|
@ -163,7 +163,7 @@ public class FeedSettingsFragment extends Fragment {
|
|||
|
||||
long feedId = getArguments().getLong(EXTRA_FEED_ID);
|
||||
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
|
||||
Feed feed = DBReader.getFeed(feedId);
|
||||
Feed feed = DBReader.getFeed(feedId, false, 0, 0);
|
||||
if (feed != null) {
|
||||
emitter.onSuccess(feed);
|
||||
} else {
|
||||
|
|
|
@ -526,7 +526,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
if (didPressSubscribe) {
|
||||
didPressSubscribe = false;
|
||||
|
||||
Feed feed1 = DBReader.getFeed(getFeedId());
|
||||
Feed feed1 = DBReader.getFeed(getFeedId(), false, 0, 0);
|
||||
FeedPreferences feedPreferences = feed1.getPreferences();
|
||||
if (UserPreferences.isEnableAutodownload()) {
|
||||
boolean autoDownload = viewBinding.autoDownloadCheckBox.isChecked();
|
||||
|
|
|
@ -76,7 +76,7 @@ public class FeedUpdateWorker extends Worker {
|
|||
}
|
||||
Collections.shuffle(toUpdate); // If the worker gets cancelled early, every feed has a chance to be updated
|
||||
} else {
|
||||
Feed feed = DBReader.getFeed(feedId);
|
||||
Feed feed = DBReader.getFeed(feedId, false, 0, Integer.MAX_VALUE);
|
||||
if (feed == null) {
|
||||
return Result.success();
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ public class DbReaderTest {
|
|||
List<FeedItem> items = feed.getItems();
|
||||
feed.setItems(null);
|
||||
List<FeedItem> savedItems = DBReader.getFeedItemList(feed,
|
||||
FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD);
|
||||
FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE);
|
||||
assertNotNull(savedItems);
|
||||
assertEquals(items.size(), savedItems.size());
|
||||
for (int i = 0; i < savedItems.size(); i++) {
|
||||
|
|
|
@ -133,7 +133,7 @@ public class DbTasksTest {
|
|||
|
||||
updatedFeedTest(newFeed, feedID, itemIDs, numItemsOld, numItemsNew);
|
||||
|
||||
final Feed feedFromDB = DBReader.getFeed(newFeed.getId());
|
||||
final Feed feedFromDB = DBReader.getFeed(newFeed.getId(), false, 0, Integer.MAX_VALUE);
|
||||
assertNotNull(feedFromDB);
|
||||
assertEquals(newFeed.getId(), feedFromDB.getId());
|
||||
updatedFeedTest(feedFromDB, feedID, itemIDs, numItemsOld, numItemsNew);
|
||||
|
@ -163,7 +163,7 @@ public class DbTasksTest {
|
|||
final Feed newFeed = FeedDatabaseWriter.updateFeed(context, feed, false);
|
||||
assertNotSame(newFeed, feed);
|
||||
|
||||
final Feed feedFromDB = DBReader.getFeed(newFeed.getId());
|
||||
final Feed feedFromDB = DBReader.getFeed(newFeed.getId(), false, 0, Integer.MAX_VALUE);
|
||||
final FeedItem feedItemFromDB = feedFromDB.getItems().get(0);
|
||||
assertTrue(feedItemFromDB.isNew());
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ public class DbTasksTest {
|
|||
Feed newFeed = FeedDatabaseWriter.updateFeed(context, feed, true);
|
||||
assertEquals(8, newFeed.getItems().size()); // 10 - 2 = 8 items
|
||||
|
||||
Feed feedFromDB = DBReader.getFeed(newFeed.getId());
|
||||
Feed feedFromDB = DBReader.getFeed(newFeed.getId(), false, 0, Integer.MAX_VALUE);
|
||||
assertEquals(8, feedFromDB.getItems().size()); // 10 - 2 = 8 items
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ public class DbTasksTest {
|
|||
Feed newFeed = FeedDatabaseWriter.updateFeed(context, feed, false);
|
||||
assertEquals(10, newFeed.getItems().size()); // id 1-duplicate replaces because the stream url is the same
|
||||
|
||||
Feed feedFromDB = DBReader.getFeed(newFeed.getId());
|
||||
Feed feedFromDB = DBReader.getFeed(newFeed.getId(), false, 0, Integer.MAX_VALUE);
|
||||
assertEquals(10, feedFromDB.getItems().size()); // id1-duplicate should override id 1
|
||||
|
||||
FeedItem updatedItem = feedFromDB.getItemAtIndex(9);
|
||||
|
|
|
@ -771,7 +771,7 @@ public class DbWriterTest {
|
|||
|
||||
DBWriter.removeAllNewFlags().get();
|
||||
List<FeedItem> loadedItems = DBReader.getFeedItemList(feed,
|
||||
FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD);
|
||||
FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE);
|
||||
for (FeedItem item : loadedItems) {
|
||||
assertFalse(item.isNew());
|
||||
}
|
||||
|
|
|
@ -169,7 +169,8 @@ public class LocalFeedUpdaterTest {
|
|||
callUpdateFeed(LOCAL_FEED_DIR1);
|
||||
|
||||
Feed feed = verifySingleFeedInDatabase();
|
||||
List<FeedItem> feedItems = DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD);
|
||||
List<FeedItem> feedItems = DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(),
|
||||
SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE);
|
||||
assertEquals("track1.mp3", feedItems.get(0).getTitle());
|
||||
}
|
||||
|
||||
|
@ -283,7 +284,8 @@ public class LocalFeedUpdaterTest {
|
|||
*/
|
||||
private static void verifySingleFeedInDatabaseAndItemCount(int expectedItemCount) {
|
||||
Feed feed = verifySingleFeedInDatabase();
|
||||
List<FeedItem> feedItems = DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD);
|
||||
List<FeedItem> feedItems = DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(),
|
||||
SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE);
|
||||
assertEquals(expectedItemCount, feedItems.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ import de.danoeh.antennapod.model.feed.FeedItem;
|
|||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import de.danoeh.antennapod.model.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
||||
import de.danoeh.antennapod.model.playback.MediaType;
|
||||
import de.danoeh.antennapod.model.playback.Playable;
|
||||
import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer;
|
||||
|
@ -452,12 +451,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
|||
new FeedItemFilter(FeedItemFilter.UNPLAYED), UserPreferences.getAllEpisodesSortOrder());
|
||||
} else if (parentId.startsWith("FeedId:")) {
|
||||
long feedId = Long.parseLong(parentId.split(":")[1]);
|
||||
Feed feed = DBReader.getFeed(feedId);
|
||||
SortOrder sortOrder = feed.getSortOrder();
|
||||
if (sortOrder == null) {
|
||||
sortOrder = SortOrder.DATE_NEW_OLD;
|
||||
}
|
||||
feedItems = DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(), sortOrder);
|
||||
feedItems = DBReader.getFeed(feedId, true, 0, MAX_ANDROID_AUTO_EPISODES_PER_FEED).getItems();
|
||||
} else if (parentId.equals(getString(R.string.current_playing_episode))) {
|
||||
FeedMedia playable = DBReader.getFeedMedia(PlaybackPreferences.getCurrentlyPlayingFeedMediaId());
|
||||
if (playable != null) {
|
||||
|
|
|
@ -149,12 +149,14 @@ public final class DBReader {
|
|||
* @param feed The Feed whose items should be loaded
|
||||
* @return A list with the FeedItems of the Feed. The Feed-attribute of the FeedItems will already be set correctly.
|
||||
*/
|
||||
public static List<FeedItem> getFeedItemList(final Feed feed, final FeedItemFilter filter, SortOrder sortOrder) {
|
||||
public static List<FeedItem> getFeedItemList(final Feed feed, final FeedItemFilter filter, SortOrder sortOrder,
|
||||
int offset, int limit) {
|
||||
Log.d(TAG, "getFeedItemList() called with: " + "feed = [" + feed + "]");
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
try (FeedItemCursor cursor = new FeedItemCursor(adapter.getItemsOfFeedCursor(feed, filter, sortOrder))) {
|
||||
try (FeedItemCursor cursor = new FeedItemCursor(adapter.getItemsOfFeedCursor(
|
||||
feed, filter, sortOrder, offset, limit))) {
|
||||
List<FeedItem> items = extractItemlistFromCursor(cursor);
|
||||
feed.setItems(items);
|
||||
for (FeedItem item : items) {
|
||||
|
@ -266,6 +268,19 @@ public final class DBReader {
|
|||
}
|
||||
}
|
||||
|
||||
public static int getFeedEpisodeCount(long feedId, FeedItemFilter filter) {
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
try (Cursor cursor = adapter.getFeedEpisodeCountCursor(feedId, filter)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
return -1;
|
||||
} finally {
|
||||
adapter.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<FeedItem> getRandomEpisodes(int limit, int seed) {
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
|
@ -324,18 +339,6 @@ public final class DBReader {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a specific Feed from the database.
|
||||
*
|
||||
* @param feedId The ID of the Feed
|
||||
* @return The Feed or null if the Feed could not be found. The Feeds FeedItems will also be loaded from the
|
||||
* database and the items-attribute will be set correctly.
|
||||
*/
|
||||
@Nullable
|
||||
public static Feed getFeed(final long feedId) {
|
||||
return getFeed(feedId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a specific Feed from the database.
|
||||
*
|
||||
|
@ -345,7 +348,7 @@ public final class DBReader {
|
|||
* database and the items-attribute will be set correctly.
|
||||
*/
|
||||
@Nullable
|
||||
public static Feed getFeed(final long feedId, boolean filtered) {
|
||||
public static Feed getFeed(final long feedId, boolean filtered, int offset, int limit) {
|
||||
Log.d(TAG, "getFeed() called with: " + "feedId = [" + feedId + "]");
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
|
@ -354,7 +357,12 @@ public final class DBReader {
|
|||
if (cursor.moveToNext()) {
|
||||
feed = cursor.getFeed();
|
||||
FeedItemFilter filter = filtered ? feed.getItemFilter() : FeedItemFilter.unfiltered();
|
||||
feed.setItems(getFeedItemList(feed, filter, feed.getSortOrder()));
|
||||
List<FeedItem> items = getFeedItemList(feed, filter, feed.getSortOrder(), offset, limit);
|
||||
for (FeedItem item : items) {
|
||||
item.setFeed(feed);
|
||||
}
|
||||
loadTagsOfFeedItemList(items);
|
||||
feed.setItems(items);
|
||||
} else {
|
||||
Log.e(TAG, "getFeed could not find feed with id " + feedId);
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ public class DBWriter {
|
|||
*/
|
||||
public static Future<?> deleteFeed(final Context context, final long feedId) {
|
||||
return runOnDbThread(() -> {
|
||||
final Feed feed = DBReader.getFeed(feedId, false);
|
||||
final Feed feed = DBReader.getFeed(feedId, false, 0, Integer.MAX_VALUE);
|
||||
if (feed == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -31,12 +31,13 @@ public abstract class FeedDatabaseWriter {
|
|||
|
||||
private static Feed searchFeedByIdentifyingValueOrID(Feed feed) {
|
||||
if (feed.getId() != 0) {
|
||||
return DBReader.getFeed(feed.getId());
|
||||
return DBReader.getFeed(feed.getId(), false, 0, Integer.MAX_VALUE);
|
||||
} else {
|
||||
List<Feed> feeds = DBReader.getFeedList();
|
||||
for (Feed f : feeds) {
|
||||
if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) {
|
||||
f.setItems(DBReader.getFeedItemList(f, FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD));
|
||||
f.setItems(DBReader.getFeedItemList(f, FeedItemFilter.unfiltered(),
|
||||
SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE));
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -954,14 +954,16 @@ public class PodDBAdapter {
|
|||
* @param feed The feed you want to get the FeedItems from.
|
||||
* @return The cursor of the query
|
||||
*/
|
||||
public final Cursor getItemsOfFeedCursor(final Feed feed, FeedItemFilter filter, SortOrder sortOrder) {
|
||||
public final Cursor getItemsOfFeedCursor(final Feed feed, FeedItemFilter filter, SortOrder sortOrder,
|
||||
int offset, int limit) {
|
||||
String orderByQuery = FeedItemSortQuery.generateFrom(sortOrder);
|
||||
String filterQuery = FeedItemFilterQuery.generateFrom(filter);
|
||||
String whereClauseAnd = "".equals(filterQuery) ? "" : " AND " + filterQuery;
|
||||
final String query = SELECT_FEED_ITEMS_AND_MEDIA
|
||||
+ " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + feed.getId()
|
||||
+ whereClauseAnd
|
||||
+ " ORDER BY " + orderByQuery;
|
||||
+ " ORDER BY " + orderByQuery
|
||||
+ " LIMIT " + offset + ", " + limit;
|
||||
return db.rawQuery(query, null);
|
||||
}
|
||||
|
||||
|
@ -1082,6 +1084,15 @@ public class PodDBAdapter {
|
|||
return db.rawQuery(query, null);
|
||||
}
|
||||
|
||||
public final Cursor getFeedEpisodeCountCursor(long feedId, FeedItemFilter filter) {
|
||||
String filterQuery = FeedItemFilterQuery.generateFrom(filter);
|
||||
String whereAndClause = "".equals(filterQuery) ? "" : " AND " + filterQuery;
|
||||
final String query = "SELECT count(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ") FROM " + TABLE_NAME_FEED_ITEMS
|
||||
+ JOIN_FEED_ITEM_AND_MEDIA
|
||||
+ " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + feedId + whereAndClause;
|
||||
return db.rawQuery(query, null);
|
||||
}
|
||||
|
||||
public Cursor getRandomEpisodesCursor(int limit, int seed) {
|
||||
final String allItemsRandomOrder = SELECT_FEED_ITEMS_AND_MEDIA
|
||||
+ " WHERE (" + KEY_READ + " = " + FeedItem.NEW + " OR " + KEY_READ + " = " + FeedItem.UNPLAYED + ") "
|
||||
|
|
|
@ -78,7 +78,7 @@ public class FeedStatisticsFragment extends Fragment {
|
|||
for (StatisticsItem statisticsItem : statisticsData.feedTime) {
|
||||
if (statisticsItem.feed.getId() == feedId) {
|
||||
List<FeedItem> items = DBReader.getFeedItemList(statisticsItem.feed,
|
||||
FeedItemFilter.unfiltered(), SortOrder.DATE_OLD_NEW);
|
||||
FeedItemFilter.unfiltered(), SortOrder.DATE_OLD_NEW, 0, Integer.MAX_VALUE);
|
||||
List<Date> dates = new ArrayList<>();
|
||||
for (FeedItem item : items) {
|
||||
dates.add(item.getPubDate());
|
||||
|
|
Loading…
Reference in New Issue