Use a publisher to get manga details. Refactor CatalogueListPresenter
This commit is contained in:
parent
ed76520ebc
commit
8dc7c550ad
3 changed files with 98 additions and 66 deletions
|
@ -1,6 +1,9 @@
|
||||||
package eu.kanade.mangafeed.presenter;
|
package eu.kanade.mangafeed.presenter;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -41,6 +44,7 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
private Subscription mSearchViewSubscription;
|
private Subscription mSearchViewSubscription;
|
||||||
private Subscription mMangaDetailFetchSubscription;
|
private Subscription mMangaDetailFetchSubscription;
|
||||||
private PublishSubject<Observable<String>> mSearchViewPublishSubject;
|
private PublishSubject<Observable<String>> mSearchViewPublishSubject;
|
||||||
|
private PublishSubject<Observable<List<Manga>>> mMangaDetailPublishSubject;
|
||||||
|
|
||||||
|
|
||||||
public CatalogueListPresenter(CatalogueListView view) {
|
public CatalogueListPresenter(CatalogueListView view) {
|
||||||
|
@ -49,17 +53,79 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
initializeSource();
|
||||||
|
initializeAdapter();
|
||||||
|
initializeSearch();
|
||||||
|
initializeMangaDetailsLoader();
|
||||||
|
|
||||||
|
getMangasFromSource(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeSource() {
|
||||||
int sourceId = view.getIntent().getIntExtra(Intent.EXTRA_UID, -1);
|
int sourceId = view.getIntent().getIntExtra(Intent.EXTRA_UID, -1);
|
||||||
selectedSource = sourceManager.get(sourceId);
|
selectedSource = sourceManager.get(sourceId);
|
||||||
view.setSourceTitle(selectedSource.getName());
|
view.setSourceTitle(selectedSource.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeAdapter() {
|
||||||
adapter = new EasyAdapter<>(view.getActivity(), CatalogueListHolder.class);
|
adapter = new EasyAdapter<>(view.getActivity(), CatalogueListHolder.class);
|
||||||
view.setAdapter(adapter);
|
view.setAdapter(adapter);
|
||||||
view.setScrollListener();
|
view.setScrollListener();
|
||||||
|
}
|
||||||
|
|
||||||
initializeSearch();
|
private void initializeSearch() {
|
||||||
|
mSearchName = "";
|
||||||
|
mSearchMode = false;
|
||||||
|
mSearchViewPublishSubject = PublishSubject.create();
|
||||||
|
|
||||||
getMangasFromSource(1);
|
mSearchViewSubscription = Observable.switchOnNext(mSearchViewPublishSubject)
|
||||||
|
.debounce(SEARCH_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
this::queryFromSearch,
|
||||||
|
error -> Timber.e(error.getCause(), error.getMessage()));
|
||||||
|
|
||||||
|
subscriptions.add(mSearchViewSubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeMangaDetailsLoader() {
|
||||||
|
mMangaDetailPublishSubject = PublishSubject.create();
|
||||||
|
|
||||||
|
mMangaDetailFetchSubscription = Observable.switchOnNext(mMangaDetailPublishSubject)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.flatMap(Observable::from)
|
||||||
|
.filter(manga -> !manga.initialized)
|
||||||
|
.buffer(5)
|
||||||
|
.concatMap(localMangas -> {
|
||||||
|
List<Observable<Manga>> mangaObservables = new ArrayList<>();
|
||||||
|
for (Manga manga : localMangas) {
|
||||||
|
Observable<Manga> tempObs = selectedSource.pullMangaFromNetwork(manga.url)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.flatMap(networkManga -> {
|
||||||
|
Manga.copyFromNetwork(manga, networkManga);
|
||||||
|
db.insertMangaBlock(manga);
|
||||||
|
return Observable.just(manga);
|
||||||
|
});
|
||||||
|
mangaObservables.add(tempObs);
|
||||||
|
}
|
||||||
|
return Observable.merge(mangaObservables);
|
||||||
|
})
|
||||||
|
.filter(manga -> manga.initialized)
|
||||||
|
.onBackpressureBuffer()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(manga -> {
|
||||||
|
// Get manga index in the adapter
|
||||||
|
int index = getMangaIndex(manga);
|
||||||
|
// Get the image view associated with the manga.
|
||||||
|
// If it's null (not visible in the screen) there's no need to update the image.
|
||||||
|
ImageView imageView = view.getImageView(index);
|
||||||
|
if (imageView != null) {
|
||||||
|
updateImage(imageView, manga.thumbnail_url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
subscriptions.add(mMangaDetailFetchSubscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getMangasFromSource(int page) {
|
public void getMangasFromSource(int page) {
|
||||||
|
@ -73,7 +139,7 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
.toList()
|
.toList()
|
||||||
.subscribe(newMangas -> {
|
.subscribe(newMangas -> {
|
||||||
adapter.addItems(newMangas);
|
adapter.addItems(newMangas);
|
||||||
getMangaDetails(newMangas);
|
mMangaDetailPublishSubject.onNext(Observable.just(newMangas));
|
||||||
});
|
});
|
||||||
|
|
||||||
subscriptions.add(mMangaFetchSubscription);
|
subscriptions.add(mMangaFetchSubscription);
|
||||||
|
@ -90,7 +156,7 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
.toList()
|
.toList()
|
||||||
.subscribe(newMangas -> {
|
.subscribe(newMangas -> {
|
||||||
adapter.addItems(newMangas);
|
adapter.addItems(newMangas);
|
||||||
getMangaDetails(newMangas);
|
mMangaDetailPublishSubject.onNext(Observable.just(newMangas));
|
||||||
});
|
});
|
||||||
|
|
||||||
subscriptions.add(mMangaSearchSubscription);
|
subscriptions.add(mMangaSearchSubscription);
|
||||||
|
@ -105,61 +171,11 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
return localManga;
|
return localManga;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getMangaDetails(List<Manga> mangas) {
|
|
||||||
subscriptions.remove(mMangaDetailFetchSubscription);
|
|
||||||
|
|
||||||
mMangaDetailFetchSubscription = Observable.from(mangas)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.filter(manga -> !manga.initialized)
|
|
||||||
.buffer(3)
|
|
||||||
.concatMap(localMangas -> {
|
|
||||||
List<Observable<Manga>> mangaObservables = new ArrayList<>();
|
|
||||||
for (Manga manga : localMangas) {
|
|
||||||
Observable<Manga> tempObs = selectedSource.pullMangaFromNetwork(manga.url)
|
|
||||||
.flatMap(networkManga -> {
|
|
||||||
Manga.copyFromNetwork(manga, networkManga);
|
|
||||||
db.insertMangaBlock(manga);
|
|
||||||
return Observable.just(manga);
|
|
||||||
})
|
|
||||||
.subscribeOn(Schedulers.io());
|
|
||||||
mangaObservables.add(tempObs);
|
|
||||||
}
|
|
||||||
return Observable.merge(mangaObservables);
|
|
||||||
})
|
|
||||||
.filter(manga -> manga.initialized)
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(manga -> {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < adapter.getCount(); i++) {
|
|
||||||
if (manga.id == adapter.getItem(i).id) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.updateImage(i, manga.thumbnail_url);
|
|
||||||
});
|
|
||||||
|
|
||||||
subscriptions.add(mMangaDetailFetchSubscription);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onQueryTextChange(String query) {
|
public void onQueryTextChange(String query) {
|
||||||
if (mSearchViewPublishSubject != null)
|
if (mSearchViewPublishSubject != null)
|
||||||
mSearchViewPublishSubject.onNext(Observable.just(query));
|
mSearchViewPublishSubject.onNext(Observable.just(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeSearch() {
|
|
||||||
mSearchName = "";
|
|
||||||
mSearchMode = false;
|
|
||||||
mSearchViewPublishSubject = PublishSubject.create();
|
|
||||||
mSearchViewSubscription = Observable.switchOnNext(mSearchViewPublishSubject)
|
|
||||||
.debounce(SEARCH_TIMEOUT, TimeUnit.MILLISECONDS)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(
|
|
||||||
this::queryFromSearch,
|
|
||||||
error -> Timber.e(error.getCause(), error.getMessage()));
|
|
||||||
|
|
||||||
subscriptions.add(mSearchViewSubscription);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void queryFromSearch(String query) {
|
private void queryFromSearch(String query) {
|
||||||
// If search button clicked
|
// If search button clicked
|
||||||
|
@ -189,4 +205,21 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getMangaIndex(Manga manga) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < adapter.getCount(); i++) {
|
||||||
|
if (manga.id == adapter.getItem(i).id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateImage(ImageView imageView, String thumbnail) {
|
||||||
|
Glide.with(view.getActivity())
|
||||||
|
.load(thumbnail)
|
||||||
|
.centerCrop()
|
||||||
|
.into(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,6 @@ import android.view.View;
|
||||||
import android.widget.GridView;
|
import android.widget.GridView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
|
@ -72,14 +70,19 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CatalogueListView
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setSourceTitle(String title) {
|
public void setSourceTitle(String title) {
|
||||||
setToolbarTitle(title);
|
setToolbarTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setAdapter(EasyAdapter adapter) {
|
public void setAdapter(EasyAdapter adapter) {
|
||||||
manga_list.setAdapter(adapter);
|
manga_list.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setScrollListener() {
|
public void setScrollListener() {
|
||||||
scrollListener = new EndlessScrollListener() {
|
scrollListener = new EndlessScrollListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -92,23 +95,19 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
|
||||||
manga_list.setOnScrollListener(scrollListener);
|
manga_list.setOnScrollListener(scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void resetScrollListener() {
|
public void resetScrollListener() {
|
||||||
scrollListener.resetScroll();
|
scrollListener.resetScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateImage(int position, String thumbnail) {
|
public ImageView getImageView(int position) {
|
||||||
View v = manga_list.getChildAt(position -
|
View v = manga_list.getChildAt(position -
|
||||||
manga_list.getFirstVisiblePosition());
|
manga_list.getFirstVisiblePosition());
|
||||||
|
|
||||||
if(v == null)
|
if(v == null)
|
||||||
return;
|
return null;
|
||||||
|
|
||||||
ImageView imageView = (ImageView) v.findViewById(R.id.catalogue_thumbnail);
|
return (ImageView) v.findViewById(R.id.catalogue_thumbnail);
|
||||||
|
|
||||||
Glide.with(getActivity())
|
|
||||||
.load(thumbnail)
|
|
||||||
.centerCrop()
|
|
||||||
.into(imageView);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package eu.kanade.mangafeed.view;
|
package eu.kanade.mangafeed.view;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.sources.Source;
|
|
||||||
import uk.co.ribot.easyadapter.EasyAdapter;
|
import uk.co.ribot.easyadapter.EasyAdapter;
|
||||||
|
|
||||||
public interface CatalogueListView extends BaseView {
|
public interface CatalogueListView extends BaseView {
|
||||||
|
@ -11,5 +11,5 @@ public interface CatalogueListView extends BaseView {
|
||||||
void setAdapter(EasyAdapter adapter);
|
void setAdapter(EasyAdapter adapter);
|
||||||
void setScrollListener();
|
void setScrollListener();
|
||||||
void resetScrollListener();
|
void resetScrollListener();
|
||||||
void updateImage(int position, String thumbnail);
|
ImageView getImageView(int position);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue