Add lazy loading to feed item list (#7091)

This commit is contained in:
ByteHamster 2024-04-13 19:18:13 +02:00 committed by GitHub
parent 04fab47072
commit f3bca9d9e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 167 additions and 101 deletions

View File

@ -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;

View File

@ -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();
}

View File

@ -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 {

View File

@ -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);
}
return feed;
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;
}
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);
}
}
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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();

View File

@ -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();
}

View File

@ -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++) {

View File

@ -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);

View File

@ -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());
}

View File

@ -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());
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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 + ") "

View File

@ -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());