Browse Source

Use a publisher to get manga details. Refactor CatalogueListPresenter

inorichi 9 years ago
parent
commit
8dc7c550ad

+ 87 - 54
app/src/main/java/eu/kanade/mangafeed/presenter/CatalogueListPresenter.java

@@ -1,6 +1,9 @@
 package eu.kanade.mangafeed.presenter;
 
 import android.content.Intent;
+import android.widget.ImageView;
+
+import com.bumptech.glide.Glide;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -41,6 +44,7 @@ public class CatalogueListPresenter extends BasePresenter {
     private Subscription mSearchViewSubscription;
     private Subscription mMangaDetailFetchSubscription;
     private PublishSubject<Observable<String>> mSearchViewPublishSubject;
+    private PublishSubject<Observable<List<Manga>>> mMangaDetailPublishSubject;
 
 
     public CatalogueListPresenter(CatalogueListView view) {
@@ -49,17 +53,79 @@ public class CatalogueListPresenter extends BasePresenter {
     }
 
     public void initialize() {
+        initializeSource();
+        initializeAdapter();
+        initializeSearch();
+        initializeMangaDetailsLoader();
+
+        getMangasFromSource(1);
+    }
+
+    private void initializeSource() {
         int sourceId = view.getIntent().getIntExtra(Intent.EXTRA_UID, -1);
         selectedSource = sourceManager.get(sourceId);
         view.setSourceTitle(selectedSource.getName());
+    }
 
+    private void initializeAdapter() {
         adapter = new EasyAdapter<>(view.getActivity(), CatalogueListHolder.class);
         view.setAdapter(adapter);
         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) {
@@ -73,7 +139,7 @@ public class CatalogueListPresenter extends BasePresenter {
                 .toList()
                 .subscribe(newMangas -> {
                     adapter.addItems(newMangas);
-                    getMangaDetails(newMangas);
+                    mMangaDetailPublishSubject.onNext(Observable.just(newMangas));
                 });
 
         subscriptions.add(mMangaFetchSubscription);
@@ -90,7 +156,7 @@ public class CatalogueListPresenter extends BasePresenter {
                 .toList()
                 .subscribe(newMangas -> {
                     adapter.addItems(newMangas);
-                    getMangaDetails(newMangas);
+                    mMangaDetailPublishSubject.onNext(Observable.just(newMangas));
                 });
 
         subscriptions.add(mMangaSearchSubscription);
@@ -105,61 +171,11 @@ public class CatalogueListPresenter extends BasePresenter {
         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) {
         if (mSearchViewPublishSubject != null)
             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) {
         // 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);
+    }
+
 }

+ 9 - 10
app/src/main/java/eu/kanade/mangafeed/ui/activity/CatalogueListActivity.java

@@ -8,8 +8,6 @@ import android.view.View;
 import android.widget.GridView;
 import android.widget.ImageView;
 
-import com.bumptech.glide.Glide;
-
 import butterknife.Bind;
 import butterknife.ButterKnife;
 import eu.kanade.mangafeed.R;
@@ -72,14 +70,19 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
         });
     }
 
+    // CatalogueListView
+
+    @Override
     public void setSourceTitle(String title) {
         setToolbarTitle(title);
     }
 
+    @Override
     public void setAdapter(EasyAdapter adapter) {
         manga_list.setAdapter(adapter);
     }
 
+    @Override
     public void setScrollListener() {
         scrollListener = new EndlessScrollListener() {
             @Override
@@ -92,23 +95,19 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
         manga_list.setOnScrollListener(scrollListener);
     }
 
+    @Override
     public void resetScrollListener() {
         scrollListener.resetScroll();
     }
 
     @Override
-    public void updateImage(int position, String thumbnail) {
+    public ImageView getImageView(int position) {
         View v = manga_list.getChildAt(position -
                 manga_list.getFirstVisiblePosition());
 
         if(v == null)
-            return;
-
-        ImageView imageView = (ImageView) v.findViewById(R.id.catalogue_thumbnail);
+            return null;
 
-        Glide.with(getActivity())
-                .load(thumbnail)
-                .centerCrop()
-                .into(imageView);
+        return (ImageView) v.findViewById(R.id.catalogue_thumbnail);
     }
 }

+ 2 - 2
app/src/main/java/eu/kanade/mangafeed/view/CatalogueListView.java

@@ -1,8 +1,8 @@
 package eu.kanade.mangafeed.view;
 
 import android.content.Intent;
+import android.widget.ImageView;
 
-import eu.kanade.mangafeed.sources.Source;
 import uk.co.ribot.easyadapter.EasyAdapter;
 
 public interface CatalogueListView extends BaseView {
@@ -11,5 +11,5 @@ public interface CatalogueListView extends BaseView {
     void setAdapter(EasyAdapter adapter);
     void setScrollListener();
     void resetScrollListener();
-    void updateImage(int position, String thumbnail);
+    ImageView getImageView(int position);
 }