Load catalogue with thumbnails

This commit is contained in:
inorichi 2015-10-13 20:16:15 +02:00
parent c88d8f0ded
commit ed76520ebc
7 changed files with 173 additions and 37 deletions

View file

@ -3,6 +3,7 @@ package eu.kanade.mangafeed.presenter;
import android.content.Intent; import android.content.Intent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
@ -38,6 +39,7 @@ public class CatalogueListPresenter extends BasePresenter {
private Subscription mMangaFetchSubscription; private Subscription mMangaFetchSubscription;
private Subscription mMangaSearchSubscription; private Subscription mMangaSearchSubscription;
private Subscription mSearchViewSubscription; private Subscription mSearchViewSubscription;
private Subscription mMangaDetailFetchSubscription;
private PublishSubject<Observable<String>> mSearchViewPublishSubject; private PublishSubject<Observable<String>> mSearchViewPublishSubject;
@ -69,7 +71,10 @@ public class CatalogueListPresenter extends BasePresenter {
.flatMap(Observable::from) .flatMap(Observable::from)
.map(this::networkToLocalManga) .map(this::networkToLocalManga)
.toList() .toList()
.subscribe(adapter::addItems); .subscribe(newMangas -> {
adapter.addItems(newMangas);
getMangaDetails(newMangas);
});
subscriptions.add(mMangaFetchSubscription); subscriptions.add(mMangaFetchSubscription);
} }
@ -83,7 +88,10 @@ public class CatalogueListPresenter extends BasePresenter {
.flatMap(Observable::from) .flatMap(Observable::from)
.map(this::networkToLocalManga) .map(this::networkToLocalManga)
.toList() .toList()
.subscribe(adapter::addItems); .subscribe(newMangas -> {
adapter.addItems(newMangas);
getMangaDetails(newMangas);
});
subscriptions.add(mMangaSearchSubscription); subscriptions.add(mMangaSearchSubscription);
} }
@ -97,23 +105,40 @@ public class CatalogueListPresenter extends BasePresenter {
return localManga; return localManga;
} }
private Observable<Manga> getMangaDetails(Manga manga) { private void getMangaDetails(List<Manga> mangas) {
Observable<Manga> mangaObs = Observable.just(manga); subscriptions.remove(mMangaDetailFetchSubscription);
if (!manga.initialized) {
return mangaObs mMangaDetailFetchSubscription = Observable.from(mangas)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.flatMap(localManga -> { .filter(manga -> !manga.initialized)
Timber.e("Request " + localManga.url); .buffer(3)
return selectedSource.pullMangaFromNetwork(localManga.url); .concatMap(localMangas -> {
}) List<Observable<Manga>> mangaObservables = new ArrayList<>();
.flatMap(networkManga -> { for (Manga manga : localMangas) {
Manga.copyFromNetwork(manga, networkManga); Observable<Manga> tempObs = selectedSource.pullMangaFromNetwork(manga.url)
Timber.w("Net manga " + manga.thumbnail_url); .flatMap(networkManga -> {
db.insertMangaBlock(manga); Manga.copyFromNetwork(manga, networkManga);
return Observable.just(manga); db.insertMangaBlock(manga);
}); return Observable.just(manga);
} })
return mangaObs; .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) {
@ -152,8 +177,8 @@ public class CatalogueListPresenter extends BasePresenter {
mSearchName = query; mSearchName = query;
adapter.getItems().clear(); adapter.getItems().clear();
view.resetScrollListener();
loadMoreMangas(1); loadMoreMangas(1);
view.setScrollListener();
} }
public void loadMoreMangas(int page) { public void loadMoreMangas(int page) {

View file

@ -4,7 +4,11 @@ import android.os.Bundle;
import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.Menu; import android.view.Menu;
import android.widget.ListView; import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
@ -19,11 +23,13 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
@Bind(R.id.toolbar) @Bind(R.id.toolbar)
Toolbar toolbar; Toolbar toolbar;
@Bind(R.id.catalogue_manga_list) @Bind(R.id.gridView)
ListView manga_list; GridView manga_list;
private CatalogueListPresenter presenter; private CatalogueListPresenter presenter;
private EndlessScrollListener scrollListener;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -75,13 +81,34 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
} }
public void setScrollListener() { public void setScrollListener() {
manga_list.setOnScrollListener(new EndlessScrollListener() { scrollListener = new EndlessScrollListener() {
@Override @Override
public boolean onLoadMore(int page, int totalItemsCount) { public boolean onLoadMore(int page, int totalItemsCount) {
presenter.loadMoreMangas(page); presenter.loadMoreMangas(page);
return true; return true;
} }
}); };
manga_list.setOnScrollListener(scrollListener);
} }
public void resetScrollListener() {
scrollListener.resetScroll();
}
@Override
public void updateImage(int position, String thumbnail) {
View v = manga_list.getChildAt(position -
manga_list.getFirstVisiblePosition());
if(v == null)
return;
ImageView imageView = (ImageView) v.findViewById(R.id.catalogue_thumbnail);
Glide.with(getActivity())
.load(thumbnail)
.centerCrop()
.into(imageView);
}
} }

View file

@ -1,8 +1,12 @@
package eu.kanade.mangafeed.ui.adapter; package eu.kanade.mangafeed.ui.adapter;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Manga; import eu.kanade.mangafeed.data.models.Manga;
import uk.co.ribot.easyadapter.ItemViewHolder; import uk.co.ribot.easyadapter.ItemViewHolder;
@ -16,6 +20,9 @@ public class CatalogueListHolder extends ItemViewHolder<Manga> {
@ViewId(R.id.catalogue_title) @ViewId(R.id.catalogue_title)
TextView title; TextView title;
@ViewId(R.id.catalogue_thumbnail)
ImageView image;
public CatalogueListHolder(View view) { public CatalogueListHolder(View view) {
super(view); super(view);
} }
@ -23,5 +30,17 @@ public class CatalogueListHolder extends ItemViewHolder<Manga> {
@Override @Override
public void onSetValues(Manga manga, PositionInfo positionInfo) { public void onSetValues(Manga manga, PositionInfo positionInfo) {
title.setText(manga.title); title.setText(manga.title);
String thumbnail;
if (manga.thumbnail_url != null)
thumbnail = manga.thumbnail_url;
else
thumbnail = "http://img1.wikia.nocookie.net/__cb20090524204255/starwars/images/thumb/1/1a/R2d2.jpg/400px-R2d2.jpg";
Glide.with(getContext())
.load(thumbnail)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.into(image);
} }
} }

View file

@ -10,4 +10,6 @@ public interface CatalogueListView extends BaseView {
void setSourceTitle(String title); void setSourceTitle(String title);
void setAdapter(EasyAdapter adapter); void setAdapter(EasyAdapter adapter);
void setScrollListener(); void setScrollListener();
void resetScrollListener();
void updateImage(int position, String thumbnail);
} }

View file

@ -28,6 +28,12 @@ public abstract class EndlessScrollListener implements AbsListView.OnScrollListe
this.currentPage = startPage; this.currentPage = startPage;
} }
public void resetScroll() {
this.currentPage = 0;
this.startingPageIndex = 0;
this.loading = true;
}
// This happens many times a second during a scroll, so be wary of the code you place here. // 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, // 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. // but first we check if we are waiting for the previous load to finish.

View file

@ -11,11 +11,18 @@
android:id="@+id/toolbar" android:id="@+id/toolbar"
layout="@layout/toolbar"/> layout="@layout/toolbar"/>
<ListView <GridView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/catalogue_manga_list" android:id="@+id/gridView"
tools:listitem="@layout/item_catalogue" android:padding="10dp"
/> android:clipToPadding="false"
android:verticalSpacing="8dp"
android:horizontalSpacing="8dp"
android:columnWidth="96dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:fastScrollEnabled="true"
tools:listitem="@layout/item_catalogue" />
</LinearLayout> </LinearLayout>

View file

@ -1,14 +1,64 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:background="@drawable/library_item_background"
>
<TextView <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="40dp" android:layout_height="wrap_content">
tools:text="New Text"
android:gravity="center_vertical" <ImageView
android:id="@+id/catalogue_title" /> android:layout_width="match_parent"
android:layout_height="144dp"
android:id="@+id/catalogue_thumbnail"
tools:src="@mipmap/ic_launcher"
tools:background="@color/md_red_100"/>
<eu.kanade.mangafeed.widget.PTSansTextView
android:id="@+id/unreadText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="123"
app:typeface="ptsansNarrowBold"
android:background="@color/md_red_300"
android:layout_gravity="right"
android:textSize="12sp"
android:visibility="gone"
android:textColor="@color/white"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:paddingTop="1dp"
android:paddingBottom="1dp" />
</FrameLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="36dp"
android:id="@+id/footerLinearLayout"
>
<eu.kanade.mangafeed.widget.PTSansTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
app:typeface="ptsansNarrowBold"
android:ellipsize="middle"
android:maxLines="2"
android:textColor="@color/black_87pc"
android:textSize="13sp"
android:id="@+id/catalogue_title"
android:paddingRight="8dp"
android:paddingLeft="8dp"
tools:text="Sample name"/>
</LinearLayout>
</LinearLayout> </LinearLayout>