diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 125217586..0178dda65 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,15 +27,11 @@
android:name=".ui.activity.MangaDetailActivity"
android:label="@string/title_activity_manga_detail"
android:parentActivityName=".ui.activity.MainActivity" >
-
{
private String mSearchName;
private boolean mSearchMode;
private final int SEARCH_TIMEOUT = 1000;
- private int mCurrentPage = 1;
- private Subscription mMangaFetchSubscription;
- private Subscription mMangaSearchSubscription;
+ @State protected int mCurrentPage;
+ private RxPager pager;
+
private Subscription mSearchViewSubscription;
private Subscription mMangaDetailFetchSubscription;
private PublishSubject> mSearchViewPublishSubject;
private PublishSubject>> mMangaDetailPublishSubject;
- private SubscriptionList mResultSubscriptions = new SubscriptionList();
- private final String CURRENT_PAGE = "CATALOGUE_CURRENT_PAGE";
+ private static final int GET_MANGA_LIST = 1;
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
- if (savedState != null) {
- mCurrentPage = savedState.getInt(CURRENT_PAGE);
- }
+ restartableReplay(GET_MANGA_LIST,
+ () -> pager.pages().>>concatMap(
+ page -> getMangaObs(page + 1)
+ .map(mangas -> new PageBundle<>(page, mangas))
+ .observeOn(AndroidSchedulers.mainThread())
+ ),
+ (view, page) -> {
+ view.hideProgressBar();
+ view.onAddPage(page);
+ if (mMangaDetailPublishSubject != null)
+ mMangaDetailPublishSubject.onNext(Observable.just(page.data));
+ });
- selectedSource = sourceManager.getSelectedSource();
- getMangasFromSource(mCurrentPage);
initializeSearch();
initializeMangaDetailsLoader();
}
@@ -63,24 +70,40 @@ public class CataloguePresenter extends RxPresenter {
protected void onTakeView(CatalogueActivity view) {
super.onTakeView(view);
- view.setScrollPage(mCurrentPage - 1);
-
view.setToolbarTitle(selectedSource.getName());
if (view.getAdapter().getCount() == 0)
view.showProgressBar();
}
- @Override
- protected void onSave(@NonNull Bundle state) {
- super.onSave(state);
- state.putInt(CURRENT_PAGE, mCurrentPage);
+ public void requestNext() {
+ pager.requestNext(++mCurrentPage);
}
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mResultSubscriptions.unsubscribe();
+ public void initializeRequest(int source_id) {
+ this.selectedSource = sourceManager.get(source_id);
+ restartRequest();
+ }
+
+ private void restartRequest() {
+ stop(GET_MANGA_LIST);
+ mCurrentPage = 1;
+ pager = new RxPager();
+ start(GET_MANGA_LIST);
+ }
+
+ private Observable> getMangaObs(int page) {
+ Observable> obs;
+ if (mSearchMode)
+ obs = selectedSource.searchMangasFromNetwork(mSearchName, page);
+ else
+ obs = selectedSource.pullPopularMangasFromNetwork(page);
+
+ return obs.subscribeOn(Schedulers.io())
+ .flatMap(Observable::from)
+ .map(this::networkToLocalManga)
+ .toList()
+ .observeOn(AndroidSchedulers.mainThread());
}
private void initializeSearch() {
@@ -134,36 +157,6 @@ public class CataloguePresenter extends RxPresenter {
add(mMangaDetailFetchSubscription);
}
- public void getMangasFromSource(int page) {
- mMangaFetchSubscription = getMangasSubscriber(
- selectedSource.pullPopularMangasFromNetwork(page));
-
- mResultSubscriptions.add(mMangaFetchSubscription);
- }
-
- public void getMangasFromSearch(int page) {
- mMangaSearchSubscription = getMangasSubscriber(
- selectedSource.searchMangasFromNetwork(mSearchName, page));
-
- mResultSubscriptions.add(mMangaSearchSubscription);
- }
-
- private Subscription getMangasSubscriber(Observable> mangas) {
- return mangas
- .subscribeOn(Schedulers.io())
- .flatMap(Observable::from)
- .map(this::networkToLocalManga)
- .toList()
- .observeOn(AndroidSchedulers.mainThread())
- .compose(deliverReplay())
- .subscribe(this.split((view, newMangas) -> {
- view.hideProgressBar();
- view.onMangasNext(newMangas);
- if (mMangaDetailPublishSubject != null)
- mMangaDetailPublishSubject.onNext(Observable.just(newMangas));
- }));
- }
-
private Manga networkToLocalManga(Manga networkManga) {
Manga localManga = db.getMangaBlock(networkManga.url);
if (localManga == null) {
@@ -186,31 +179,20 @@ public class CataloguePresenter extends RxPresenter {
// If going to search mode
else if (mSearchName.equals("") && !query.equals("")) {
mSearchMode = true;
- mResultSubscriptions.clear();
}
// If going to normal mode
else if (!mSearchName.equals("") && query.equals("")) {
mSearchMode = false;
- mResultSubscriptions.clear();
}
mSearchName = query;
- getView().getAdapter().getItems().clear();
- getView().showProgressBar();
- getView().resetScrollListener();
- loadMoreMangas(1);
- }
-
- public void loadMoreMangas(int page) {
- if (page > 1) {
- getView().showGridProgressBar();
+ if (getView() != null) {
+ if (mCurrentPage == 1)
+ getView().showProgressBar();
+ else
+ getView().showGridProgressBar();
}
- if (mSearchMode) {
- getMangasFromSearch(page);
- } else {
- getMangasFromSource(page);
- }
- mCurrentPage = page;
+ restartRequest();
}
}
diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/activity/CatalogueActivity.java b/app/src/main/java/eu/kanade/mangafeed/ui/activity/CatalogueActivity.java
index 64d88e1b8..067de0e43 100644
--- a/app/src/main/java/eu/kanade/mangafeed/ui/activity/CatalogueActivity.java
+++ b/app/src/main/java/eu/kanade/mangafeed/ui/activity/CatalogueActivity.java
@@ -13,6 +13,7 @@ import android.widget.ProgressBar;
import com.bumptech.glide.Glide;
+import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
@@ -22,6 +23,7 @@ import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.presenter.CataloguePresenter;
import eu.kanade.mangafeed.ui.adapter.CatalogueHolder;
+import eu.kanade.mangafeed.util.PageBundle;
import eu.kanade.mangafeed.widget.EndlessScrollListener;
import nucleus.factory.RequiresPresenter;
import uk.co.ribot.easyadapter.EasyAdapter;
@@ -62,6 +64,11 @@ public class CatalogueActivity extends BaseActivity {
initializeAdapter();
initializeScrollListener();
+
+ int source_id = getIntent().getIntExtra(SOURCE_ID, -1);
+
+ if (savedInstanceState == null)
+ getPresenter().initializeRequest(source_id);
}
@Override
@@ -107,14 +114,7 @@ public class CatalogueActivity extends BaseActivity {
}
public void initializeScrollListener() {
- scroll_listener = new EndlessScrollListener() {
- @Override
- public boolean onLoadMore(int page, int totalItemsCount) {
- getPresenter().loadMoreMangas(page);
- return true;
- }
- };
-
+ scroll_listener = new EndlessScrollListener(getPresenter()::requestNext);
manga_list.setOnScrollListener(scroll_listener);
}
@@ -122,14 +122,6 @@ public class CatalogueActivity extends BaseActivity {
scroll_listener.resetScroll();
}
- public int getScrollPage() {
- return scroll_listener.getCurrentPage();
- }
-
- public void setScrollPage(int page) {
- scroll_listener.setCurrentPage(page);
- }
-
public void showProgressBar() {
progress.setVisibility(ProgressBar.VISIBLE);
}
@@ -143,8 +135,12 @@ public class CatalogueActivity extends BaseActivity {
progress_grid.setVisibility(ProgressBar.GONE);
}
- public void onMangasNext(List newMangas) {
- adapter.addItems(newMangas);
+ public void onAddPage(PageBundle> page) {
+ if (page.page == 0) {
+ adapter.setItems(new ArrayList<>());
+ resetScrollListener();
+ }
+ adapter.addItems(page.data);
}
private int getMangaIndex(Manga manga) {
@@ -175,4 +171,5 @@ public class CatalogueActivity extends BaseActivity {
.into(imageView);
}
}
+
}
diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/activity/MangaDetailActivity.java b/app/src/main/java/eu/kanade/mangafeed/ui/activity/MangaDetailActivity.java
index 53dd5f169..48551794a 100644
--- a/app/src/main/java/eu/kanade/mangafeed/ui/activity/MangaDetailActivity.java
+++ b/app/src/main/java/eu/kanade/mangafeed/ui/activity/MangaDetailActivity.java
@@ -10,6 +10,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
import butterknife.Bind;
import butterknife.ButterKnife;
@@ -57,6 +58,16 @@ public class MangaDetailActivity extends BaseActivity {
setupViewPager();
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
private void disableToolbarElevation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setElevation(0);
diff --git a/app/src/main/java/eu/kanade/mangafeed/util/PageBundle.java b/app/src/main/java/eu/kanade/mangafeed/util/PageBundle.java
new file mode 100644
index 000000000..5ad33bdc4
--- /dev/null
+++ b/app/src/main/java/eu/kanade/mangafeed/util/PageBundle.java
@@ -0,0 +1,12 @@
+package eu.kanade.mangafeed.util;
+
+public class PageBundle {
+
+ public final int page;
+ public final T data;
+
+ public PageBundle(int page, T data) {
+ this.page = page;
+ this.data = data;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/eu/kanade/mangafeed/util/RxPager.java b/app/src/main/java/eu/kanade/mangafeed/util/RxPager.java
new file mode 100644
index 000000000..032c5898b
--- /dev/null
+++ b/app/src/main/java/eu/kanade/mangafeed/util/RxPager.java
@@ -0,0 +1,32 @@
+package eu.kanade.mangafeed.util;
+
+import rx.Observable;
+import rx.subjects.PublishSubject;
+
+public class RxPager {
+
+ private final int initialPageCount;
+ private final PublishSubject requests = PublishSubject.create();
+ private int requestedCount;
+
+ public RxPager() {
+ this(1);
+ }
+
+ public RxPager(int initialPageCount) {
+ this.initialPageCount = initialPageCount;
+ }
+
+ public void requestNext(int page) {
+ requests.onNext(page);
+ }
+
+ public Observable pages() {
+ return requests
+ .concatMap(targetPage -> targetPage <= requestedCount ?
+ Observable.never() :
+ Observable.range(requestedCount, targetPage - requestedCount))
+ .startWith(Observable.range(0, initialPageCount))
+ .doOnNext(it -> requestedCount = it + 1);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/eu/kanade/mangafeed/widget/EndlessScrollListener.java b/app/src/main/java/eu/kanade/mangafeed/widget/EndlessScrollListener.java
index 1ebeed1ef..8aff6d9b9 100644
--- a/app/src/main/java/eu/kanade/mangafeed/widget/EndlessScrollListener.java
+++ b/app/src/main/java/eu/kanade/mangafeed/widget/EndlessScrollListener.java
@@ -2,35 +2,25 @@ package eu.kanade.mangafeed.widget;
import android.widget.AbsListView;
-public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
+import rx.functions.Action0;
+
+public class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
- // The current offset index of data you have loaded
- private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
- // Sets the starting page index
- private int startingPageIndex = 0;
- public EndlessScrollListener() {
- }
+ private Action0 requestNext;
- public EndlessScrollListener(int visibleThreshold) {
- this.visibleThreshold = visibleThreshold;
- }
-
- public EndlessScrollListener(int visibleThreshold, int startPage) {
- this.visibleThreshold = visibleThreshold;
- this.startingPageIndex = startPage;
- this.currentPage = startPage;
+ public EndlessScrollListener(Action0 requestNext) {
+ this.requestNext = requestNext;
}
public void resetScroll() {
- this.currentPage = 0;
- this.startingPageIndex = 0;
+ this.previousTotalItemCount = 0;
this.loading = true;
}
@@ -43,7 +33,6 @@ public abstract class EndlessScrollListener implements AbsListView.OnScrollListe
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
- this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
@@ -53,31 +42,20 @@ public abstract class EndlessScrollListener implements AbsListView.OnScrollListe
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
- currentPage++;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) {
- loading = onLoadMore(currentPage + 1, totalItemCount);
+ requestNext.call();
+ loading = true;
}
}
- // Defines the process for actually loading more data based on page
- // Returns true if more data is being loaded; returns false if there is no more data to load.
- public abstract boolean onLoadMore(int page, int totalItemsCount);
-
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
- public int getCurrentPage() {
- return currentPage;
- }
-
- public void setCurrentPage(int currentPage) {
- this.currentPage = currentPage;
- }
}
\ No newline at end of file