mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Load more mangas on scroll
This commit is contained in:
		| @@ -102,6 +102,11 @@ public class DatabaseHelper implements MangaManager, ChapterManager { | ||||
|         return mMangaManager.getManga(id); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Manga getMangaBlock(String url) { | ||||
|         return mMangaManager.getMangaBlock(url); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Observable<PutResult> insertManga(Manga manga) { | ||||
|         return mMangaManager.insertManga(manga); | ||||
| @@ -112,6 +117,11 @@ public class DatabaseHelper implements MangaManager, ChapterManager { | ||||
|         return mMangaManager.insertMangas(mangas); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PutResult insertMangaBlock(Manga manga) { | ||||
|         return mMangaManager.insertMangaBlock(manga); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Observable<DeleteResult> deleteManga(Manga manga) { | ||||
|         return mMangaManager.deleteManga(manga); | ||||
|   | ||||
| @@ -20,10 +20,14 @@ public interface MangaManager { | ||||
|  | ||||
|     Observable<List<Manga>> getManga(int id); | ||||
|  | ||||
|     Manga getMangaBlock(String url); | ||||
|  | ||||
|     Observable<PutResult> insertManga(Manga manga); | ||||
|  | ||||
|     Observable<PutResults<Manga>> insertMangas(List<Manga> mangas); | ||||
|  | ||||
|     PutResult insertMangaBlock(Manga manga); | ||||
|  | ||||
|     Observable<DeleteResult> deleteManga(Manga manga); | ||||
|  | ||||
|     Observable<DeleteResults<Manga>> deleteMangas(List<Manga> mangas); | ||||
|   | ||||
| @@ -70,6 +70,24 @@ public class MangaManagerImpl extends BaseManager implements MangaManager { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Manga getMangaBlock(String url) { | ||||
|         List<Manga> result = db.get() | ||||
|                 .listOfObjects(Manga.class) | ||||
|                 .withQuery(Query.builder() | ||||
|                         .table(MangasTable.TABLE) | ||||
|                         .where(MangasTable.COLUMN_URL + "=?") | ||||
|                         .whereArgs(url) | ||||
|                         .build()) | ||||
|                 .prepare() | ||||
|                 .executeAsBlocking(); | ||||
|  | ||||
|         if (result.isEmpty()) | ||||
|             return null; | ||||
|  | ||||
|         return result.get(0); | ||||
|     } | ||||
|  | ||||
|     public Observable<PutResult> insertManga(Manga manga) { | ||||
|         return db.put() | ||||
|                 .object(manga) | ||||
| @@ -84,6 +102,13 @@ public class MangaManagerImpl extends BaseManager implements MangaManager { | ||||
|                 .createObservable(); | ||||
|     } | ||||
|  | ||||
|     public PutResult insertMangaBlock(Manga manga) { | ||||
|         return db.put() | ||||
|                 .object(manga) | ||||
|                 .prepare() | ||||
|                 .executeAsBlocking(); | ||||
|     } | ||||
|  | ||||
|     public Observable<DeleteResult> deleteManga(Manga manga) { | ||||
|         return db.delete() | ||||
|                 .object(manga) | ||||
|   | ||||
| @@ -83,6 +83,8 @@ public class MangasTable { | ||||
|                 + COLUMN_INITIALIZED + " BOOLEAN NOT NULL, " | ||||
|                 + COLUMN_VIEWER + " INTEGER NOT NULL, " | ||||
|                 + COLUMN_CHAPTER_ORDER + " INTEGER NOT NULL" | ||||
|                 + ");"; | ||||
|                 + ");" | ||||
|                 + "CREATE INDEX " + TABLE + "_" + COLUMN_URL + "_index ON " + TABLE + "(" + COLUMN_URL + ");"; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -12,11 +12,12 @@ import eu.kanade.mangafeed.sources.Source; | ||||
| import eu.kanade.mangafeed.ui.adapter.CatalogueListHolder; | ||||
| import eu.kanade.mangafeed.view.CatalogueListView; | ||||
| import rx.Observable; | ||||
| import rx.Subscription; | ||||
| import rx.android.schedulers.AndroidSchedulers; | ||||
| import rx.schedulers.Schedulers; | ||||
| import uk.co.ribot.easyadapter.EasyAdapter; | ||||
|  | ||||
| public class CatalogueListPresenter { | ||||
| public class CatalogueListPresenter extends BasePresenter { | ||||
|  | ||||
|     CatalogueListView view; | ||||
|     EasyAdapter<Manga> adapter; | ||||
| @@ -25,6 +26,8 @@ public class CatalogueListPresenter { | ||||
|     @Inject SourceManager sourceManager; | ||||
|     @Inject DatabaseHelper db; | ||||
|  | ||||
|     private Subscription mMangaFetchSubscription; | ||||
|  | ||||
|  | ||||
|     public CatalogueListPresenter(CatalogueListView view) { | ||||
|         this.view = view; | ||||
| @@ -38,24 +41,32 @@ public class CatalogueListPresenter { | ||||
|  | ||||
|         adapter = new EasyAdapter<>(view.getActivity(), CatalogueListHolder.class); | ||||
|         view.setAdapter(adapter); | ||||
|         view.setScrollListener(); | ||||
|  | ||||
|         getMangasFromSource(); | ||||
|         getMangasFromSource(1); | ||||
|     } | ||||
|  | ||||
|     private void getMangasFromSource() { | ||||
|         selectedSource.pullPopularMangasFromNetwork(1) | ||||
|     public void getMangasFromSource(int page) { | ||||
|         subscriptions.remove(mMangaFetchSubscription); | ||||
|  | ||||
|         mMangaFetchSubscription = selectedSource.pullPopularMangasFromNetwork(page) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .flatMap(Observable::from) | ||||
|                 .flatMap(networkManga -> db.getManga(networkManga.url) | ||||
|                         .flatMap(result -> { | ||||
|                             if (result.size() == 0) { | ||||
|                                 return db.insertManga(networkManga) | ||||
|                                         .flatMap(i -> Observable.just(networkManga)); | ||||
|                             } | ||||
|                             return Observable.just(networkManga); | ||||
|                         })) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe(adapter::addItem); | ||||
|                 .flatMap(Observable::from) | ||||
|                 .map(this::networkToLocalManga) | ||||
|                 .toList() | ||||
|                 .subscribe(adapter::addItems); | ||||
|  | ||||
|         subscriptions.add(mMangaFetchSubscription); | ||||
|     } | ||||
|  | ||||
|     private Manga networkToLocalManga(Manga networkManga) { | ||||
|         Manga localManga = db.getMangaBlock(networkManga.url); | ||||
|         if (localManga == null) { | ||||
|             db.insertMangaBlock(networkManga); | ||||
|             localManga = db.getMangaBlock(networkManga.url); | ||||
|         } | ||||
|         return localManga; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import eu.kanade.mangafeed.R; | ||||
| import eu.kanade.mangafeed.presenter.CatalogueListPresenter; | ||||
| import eu.kanade.mangafeed.sources.Source; | ||||
| import eu.kanade.mangafeed.view.CatalogueListView; | ||||
| import eu.kanade.mangafeed.widget.EndlessScrollListener; | ||||
| import uk.co.ribot.easyadapter.EasyAdapter; | ||||
|  | ||||
| public class CatalogueListActivity extends BaseActivity implements CatalogueListView { | ||||
| @@ -24,7 +25,7 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList | ||||
|     private Source source; | ||||
|  | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|     public void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_catalogue_list); | ||||
|         ButterKnife.bind(this); | ||||
| @@ -35,6 +36,12 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList | ||||
|         presenter.initializeSource(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         presenter.destroySubscriptions(); | ||||
|     } | ||||
|  | ||||
|     public void setSource(Source source) { | ||||
|         this.source = source; | ||||
|         setToolbarTitle(source.getName()); | ||||
| @@ -44,4 +51,14 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList | ||||
|         manga_list.setAdapter(adapter); | ||||
|     } | ||||
|  | ||||
|     public void setScrollListener() { | ||||
|         manga_list.setOnScrollListener(new EndlessScrollListener() { | ||||
|             @Override | ||||
|             public boolean onLoadMore(int page, int totalItemsCount) { | ||||
|                 presenter.getMangasFromSource(page); | ||||
|                 return true; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -9,4 +9,5 @@ public interface CatalogueListView extends BaseView { | ||||
|     Intent getIntent(); | ||||
|     void setSource(Source source); | ||||
|     void setAdapter(EasyAdapter adapter); | ||||
|     void setScrollListener(); | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,69 @@ | ||||
| package eu.kanade.mangafeed.widget; | ||||
|  | ||||
| import android.widget.AbsListView; | ||||
|  | ||||
| public abstract 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() { | ||||
|     } | ||||
|  | ||||
|     public EndlessScrollListener(int visibleThreshold) { | ||||
|         this.visibleThreshold = visibleThreshold; | ||||
|     } | ||||
|  | ||||
|     public EndlessScrollListener(int visibleThreshold, int startPage) { | ||||
|         this.visibleThreshold = visibleThreshold; | ||||
|         this.startingPageIndex = startPage; | ||||
|         this.currentPage = startPage; | ||||
|     } | ||||
|  | ||||
|     // This happens many times a second during a scroll, so be wary of the code you place here. | ||||
|     // We are given a few useful parameters to help us work out if we need to load some more data, | ||||
|     // but first we check if we are waiting for the previous load to finish. | ||||
|     @Override | ||||
|     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) | ||||
|     { | ||||
|         // 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; } | ||||
|         } | ||||
|         // If it’s still loading, we check to see if the dataset count has | ||||
|         // changed, if so we conclude it has finished loading and update the current page | ||||
|         // number and total item count. | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // 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 | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user