diff options
author | ByteHamster <info@bytehamster.com> | 2019-12-31 14:32:52 +0100 |
---|---|---|
committer | ByteHamster <info@bytehamster.com> | 2020-01-09 20:41:50 +0100 |
commit | 128f80fe55575b9ee105d810bd2c2c70e8a25389 (patch) | |
tree | 61934b3061b541d773cd8325d037b4c2eaa67695 /app | |
parent | 6d0b16461d5567dae4b3dd6553d53acffb766359 (diff) | |
download | AntennaPod-128f80fe55575b9ee105d810bd2c2c70e8a25389.zip |
Added paged loading to 'new episodes' list
Diffstat (limited to 'app')
6 files changed, 127 insertions, 87 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java index 647ab911f..b50c4dca6 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java @@ -267,11 +267,11 @@ public class DBReaderTest { for (int i = 0; i < newItems.size(); i++) { unreadIds[i] = newItems.get(i).getId(); } - List<FeedItem> newItemsSaved = DBReader.getNewItemsList(); + List<FeedItem> newItemsSaved = DBReader.getNewItemsList(0, Integer.MAX_VALUE); assertNotNull(newItemsSaved); assertTrue(newItems.size() == newItemsSaved.size()); - for(int i=0; i < newItemsSaved.size(); i++) { - long savedId = newItemsSaved.get(i).getId(); + for (FeedItem feedItem : newItemsSaved) { + long savedId = feedItem.getId(); boolean found = false; for (long id : unreadIds) { if (id == savedId) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index fdb74fa64..e4276b3b9 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -3,26 +3,18 @@ package de.danoeh.antennapod.fragment; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.util.Log; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.joanzapata.iconify.Iconify; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedItemFilter; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.dialog.FilterDialog; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -33,16 +25,18 @@ import java.util.Set; * supports swiping to mark as read. */ public class AllEpisodesFragment extends EpisodesListFragment { - public static final String TAG = "AllEpisodesFragment"; private static final String PREF_NAME = "PrefAllEpisodesFragment"; private static final String PREF_FILTER = "filter"; - private static final int EPISODES_PER_PAGE = 150; - private static final int VISIBLE_EPISODES_SCROLL_THRESHOLD = 5; - private static int page = 1; + private static FeedItemFilter feedItemFilter = new FeedItemFilter(""); - private FeedItemFilter feedItemFilter = new FeedItemFilter(""); + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); + feedItemFilter = new FeedItemFilter(prefs.getString(PREF_FILTER, "")); + } @Override protected boolean showOnlyNewEpisodes() { @@ -69,53 +63,6 @@ public class AllEpisodesFragment extends EpisodesListFragment { } } - @NonNull - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View root = super.onCreateView(inflater, container, savedInstanceState); - - SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - feedItemFilter = new FeedItemFilter(prefs.getString(PREF_FILTER, "")); - - recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - - /* Total number of episodes after last load */ - private int previousTotalEpisodes = 0; - - /* True if loading more episodes is still in progress */ - private boolean isLoadingMore = true; - - @Override - public void onScrolled(RecyclerView recyclerView, int deltaX, int deltaY) { - super.onScrolled(recyclerView, deltaX, deltaY); - - int visibleEpisodeCount = recyclerView.getChildCount(); - int totalEpisodeCount = recyclerView.getLayoutManager().getItemCount(); - int firstVisibleEpisode = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); - - /* Determine if loading more episodes has finished */ - if (isLoadingMore) { - if (totalEpisodeCount > previousTotalEpisodes) { - isLoadingMore = false; - previousTotalEpisodes = totalEpisodeCount; - } - } - - /* Determine if the user scrolled to the bottom and loading more episodes is not already in progress */ - if (!isLoadingMore && (totalEpisodeCount - visibleEpisodeCount) - <= (firstVisibleEpisode + VISIBLE_EPISODES_SCROLL_THRESHOLD)) { - - /* The end of the list has been reached. Load more data. */ - page++; - loadMoreItems(); - isLoadingMore = true; - } - } - }); - - return root; - } - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); @@ -136,20 +83,6 @@ public class AllEpisodesFragment extends EpisodesListFragment { } } - private void loadMoreItems() { - if (disposable != null) { - disposable.dispose(); - } - disposable = Observable.fromCallable(this::loadMoreData) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(data -> { - progLoading.setVisibility(View.GONE); - episodes.addAll(data); - onFragmentLoaded(episodes); - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } - private void showFilterDialog() { FilterDialog filterDialog = new FilterDialog(getContext(), feedItemFilter) { @Override @@ -167,10 +100,13 @@ public class AllEpisodesFragment extends EpisodesListFragment { @NonNull @Override protected List<FeedItem> loadData() { - return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE)); + return feedItemFilter.filter(DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE)); } - List<FeedItem> loadMoreData() { - return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE)); + @NonNull + @Override + protected List<FeedItem> loadMoreData() { + return feedItemFilter.filter(DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, + EPISODES_PER_PAGE)); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java index 5dbb703b7..b6d6dd9bb 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -70,9 +70,14 @@ public abstract class EpisodesListFragment extends Fragment { private static final String PREF_SCROLL_POSITION = "scroll_position"; private static final String PREF_SCROLL_OFFSET = "scroll_offset"; + protected static final int EPISODES_PER_PAGE = 150; + private static final int VISIBLE_EPISODES_SCROLL_THRESHOLD = 5; + protected int page = 1; + RecyclerView recyclerView; AllEpisodesRecycleAdapter listAdapter; ProgressBar progLoading; + View loadingMore; EmptyViewHandler emptyView; @NonNull @@ -264,6 +269,7 @@ public abstract class EpisodesListFragment extends Fragment { recyclerView.setHasFixedSize(true); recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build()); recyclerView.setVisibility(View.GONE); + setupLoadMoreScrollListener(); RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { @@ -272,6 +278,7 @@ public abstract class EpisodesListFragment extends Fragment { progLoading = root.findViewById(R.id.progLoading); progLoading.setVisibility(View.VISIBLE); + loadingMore = root.findViewById(R.id.loadingMore); emptyView = new EmptyViewHandler(getContext()); emptyView.attachToRecyclerView(recyclerView); @@ -285,6 +292,60 @@ public abstract class EpisodesListFragment extends Fragment { return root; } + private void setupLoadMoreScrollListener() { + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + + /* Total number of episodes after last load */ + private int previousTotalEpisodes = 0; + + /* True if loading more episodes is still in progress */ + private boolean isLoadingMore = true; + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int deltaX, int deltaY) { + super.onScrolled(recyclerView, deltaX, deltaY); + + int visibleEpisodeCount = recyclerView.getChildCount(); + int totalEpisodeCount = recyclerView.getLayoutManager().getItemCount(); + int firstVisibleEpisode = layoutManager.findFirstVisibleItemPosition(); + + /* Determine if loading more episodes has finished */ + if (isLoadingMore) { + if (totalEpisodeCount > previousTotalEpisodes) { + isLoadingMore = false; + previousTotalEpisodes = totalEpisodeCount; + } + } + + /* Determine if the user scrolled to the bottom and loading more episodes is not already in progress */ + if (!isLoadingMore && (totalEpisodeCount - visibleEpisodeCount) + <= (firstVisibleEpisode + VISIBLE_EPISODES_SCROLL_THRESHOLD)) { + + /* The end of the list has been reached. Load more data. */ + page++; + loadMoreItems(); + isLoadingMore = true; + } + } + }); + } + + private void loadMoreItems() { + if (disposable != null) { + disposable.dispose(); + } + loadingMore.setVisibility(View.VISIBLE); + disposable = Observable.fromCallable(this::loadMoreData) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(data -> { + loadingMore.setVisibility(View.GONE); + progLoading.setVisibility(View.GONE); + episodes.addAll(data); + onFragmentLoaded(episodes); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); + } + protected void onFragmentLoaded(List<FeedItem> episodes) { listAdapter.notifyDataSetChanged(); @@ -453,4 +514,7 @@ public abstract class EpisodesListFragment extends Fragment { @NonNull protected abstract List<FeedItem> loadData(); + + @NonNull + protected abstract List<FeedItem> loadMoreData(); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java index f73735658..87a555cfd 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java @@ -88,6 +88,12 @@ public class FavoriteEpisodesFragment extends EpisodesListFragment { @NonNull @Override protected List<FeedItem> loadData() { - return DBReader.getFavoriteItemsList(); + return DBReader.getFavoriteItemsList(0, page * EPISODES_PER_PAGE); + } + + @NonNull + @Override + protected List<FeedItem> loadMoreData() { + return DBReader.getFavoriteItemsList((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index 2bfdd040b..bd3fd06b0 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -104,6 +104,12 @@ public class NewEpisodesFragment extends EpisodesListFragment { @NonNull @Override protected List<FeedItem> loadData() { - return DBReader.getNewItemsList(); + return DBReader.getNewItemsList(0, page * EPISODES_PER_PAGE); + } + + @NonNull + @Override + protected List<FeedItem> loadMoreData() { + return DBReader.getNewItemsList((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE); } } diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml index 9160998ac..784e7a1c8 100644 --- a/app/src/main/res/layout/all_episodes_fragment.xml +++ b/app/src/main/res/layout/all_episodes_fragment.xml @@ -27,6 +27,7 @@ android:clipToPadding="false" android:paddingTop="@dimen/list_vertical_padding" android:paddingBottom="@dimen/list_vertical_padding" + android:layout_above="@id/loadingMore" app:fastScrollEnabled="true" app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable" app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable" @@ -43,9 +44,36 @@ android:indeterminateOnly="true" android:visibility="gone" android:layout_centerInParent="true" - tools:visibility="gone" - tools:layout_width="match_parent" - tools:layout_height="64dp" tools:background="@android:color/holo_red_light"/> + <LinearLayout + android:id="@+id/loadingMore" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:orientation="horizontal" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:paddingTop="4dp" + android:paddingBottom="4dp" + android:visibility="gone" + android:gravity="center"> + + <ProgressBar + android:layout_width="16dp" + android:layout_height="16dp" + android:gravity="center_horizontal" + android:indeterminateOnly="true" + android:layout_centerInParent="true" + tools:background="@android:color/holo_red_light" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="4dp" + android:layout_marginStart="4dp" + android:text="@string/loading_more" /> + + </LinearLayout> + </RelativeLayout>
\ No newline at end of file |