Cache chapter images from presenter with glide.

This commit is contained in:
inorichi 2015-10-23 01:40:27 +02:00
parent fefc6ba0e9
commit ef7613f7ad
10 changed files with 93 additions and 71 deletions

View file

@ -5,10 +5,10 @@ import android.content.Context;
import org.acra.annotation.ReportsCrashes; import org.acra.annotation.ReportsCrashes;
import eu.kanade.mangafeed.injection.component.AppComponent;
import eu.kanade.mangafeed.injection.module.AppModule;
import eu.kanade.mangafeed.injection.ComponentReflectionInjector; import eu.kanade.mangafeed.injection.ComponentReflectionInjector;
import eu.kanade.mangafeed.injection.component.AppComponent;
import eu.kanade.mangafeed.injection.component.DaggerAppComponent; import eu.kanade.mangafeed.injection.component.DaggerAppComponent;
import eu.kanade.mangafeed.injection.module.AppModule;
import timber.log.Timber; import timber.log.Timber;
@ReportsCrashes( @ReportsCrashes(

View file

@ -5,15 +5,17 @@ public class Page {
private int pageNumber; private int pageNumber;
private String url; private String url;
private String imageUrl; private String imageUrl;
private String imagePath;
public Page(int pageNumber, String url, String imageUrl) { public Page(int pageNumber, String url, String imageUrl, String imagePath) {
this.pageNumber = pageNumber; this.pageNumber = pageNumber;
this.url = url; this.url = url;
this.imageUrl = imageUrl; this.imageUrl = imageUrl;
this.imagePath = imagePath;
} }
public Page(int pageNumber, String url) { public Page(int pageNumber, String url) {
this(pageNumber, url, null); this(pageNumber, url, null, null);
} }
public int getPageNumber() { public int getPageNumber() {
@ -32,6 +34,14 @@ public class Page {
this.imageUrl = imageUrl; this.imageUrl = imageUrl;
} }
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
@Override @Override
public String toString() { public String toString() {
return "Page{" + return "Page{" +
@ -40,4 +50,5 @@ public class Page {
", imageUrl='" + imageUrl + '\'' + ", imageUrl='" + imageUrl + '\'' +
'}'; '}';
} }
} }

View file

@ -2,6 +2,9 @@ package eu.kanade.mangafeed.injection.module;
import android.app.Application; import android.app.Application;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
@ -55,4 +58,10 @@ public class DataModule {
SourceManager provideSourceManager(NetworkHelper networkHelper, CacheManager cacheManager) { SourceManager provideSourceManager(NetworkHelper networkHelper, CacheManager cacheManager) {
return new SourceManager(networkHelper, cacheManager); return new SourceManager(networkHelper, cacheManager);
} }
@Provides
@Singleton
RequestManager provideGlideDownloader(Application app) {
return Glide.with(app);
}
} }

View file

@ -13,11 +13,11 @@ import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.helpers.SourceManager; import eu.kanade.mangafeed.data.helpers.SourceManager;
import eu.kanade.mangafeed.data.models.Chapter; import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga; import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.events.ChapterCountEvent;
import eu.kanade.mangafeed.events.SourceChapterEvent;
import eu.kanade.mangafeed.sources.Source; import eu.kanade.mangafeed.sources.Source;
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment; import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.EventBusHook;
import eu.kanade.mangafeed.events.ChapterCountEvent;
import eu.kanade.mangafeed.events.SourceChapterEvent;
import rx.Observable; import rx.Observable;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;

View file

@ -6,9 +6,9 @@ import javax.inject.Inject;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper; import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.models.Manga; import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.events.ChapterCountEvent;
import eu.kanade.mangafeed.ui.fragment.MangaInfoFragment; import eu.kanade.mangafeed.ui.fragment.MangaInfoFragment;
import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.EventBusHook;
import eu.kanade.mangafeed.events.ChapterCountEvent;
import rx.Observable; import rx.Observable;
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> { public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {

View file

@ -2,6 +2,11 @@ package eu.kanade.mangafeed.presenter;
import android.os.Bundle; import android.os.Bundle;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.target.Target;
import java.io.File;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -10,10 +15,10 @@ import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.data.helpers.PreferencesHelper; import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
import eu.kanade.mangafeed.data.models.Chapter; import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Page; import eu.kanade.mangafeed.data.models.Page;
import eu.kanade.mangafeed.events.SourceChapterEvent;
import eu.kanade.mangafeed.sources.Source; import eu.kanade.mangafeed.sources.Source;
import eu.kanade.mangafeed.ui.activity.ReaderActivity; import eu.kanade.mangafeed.ui.activity.ReaderActivity;
import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.EventBusHook;
import eu.kanade.mangafeed.events.SourceChapterEvent;
import icepick.State; import icepick.State;
import rx.Observable; import rx.Observable;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
@ -22,6 +27,7 @@ import rx.schedulers.Schedulers;
public class ReaderPresenter extends BasePresenter<ReaderActivity> { public class ReaderPresenter extends BasePresenter<ReaderActivity> {
@Inject PreferencesHelper prefs; @Inject PreferencesHelper prefs;
@Inject RequestManager glideDownloader;
private Source source; private Source source;
private Chapter chapter; private Chapter chapter;
@ -97,10 +103,26 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
Observable.from(pageList).filter(page -> page.getImageUrl() != null), Observable.from(pageList).filter(page -> page.getImageUrl() != null),
source.getRemainingImageUrlsFromPageList(pageList) source.getRemainingImageUrlsFromPageList(pageList)
.doOnNext(this::replacePageUrl)) .doOnNext(this::replacePageUrl))
.flatMap(this::downloadImage)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
private Observable<Page> downloadImage(Page page) {
FutureTarget<File> future = glideDownloader.load(page.getImageUrl())
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
try {
File cacheFile = future.get();
page.setImagePath(cacheFile.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
return Observable.just(page);
}
private void replacePageUrl(Page page) { private void replacePageUrl(Page page) {
for (int i = 0; i < pageList.size(); i++) { for (int i = 0; i < pageList.size(); i++) {
if (pageList.get(i).getPageNumber() == page.getPageNumber()) { if (pageList.get(i).getPageNumber() == page.getPageNumber()) {

View file

@ -46,7 +46,7 @@ public abstract class Source {
} }
// Number of images to download at the same time // Number of images to download at the same time
protected int getNumberOfConcurrentImageDownloads() { protected int getNumberOfConcurrentPageDownloads() {
return 3; return 3;
} }
@ -111,14 +111,10 @@ public abstract class Source {
public Observable<Page> getRemainingImageUrlsFromPageList(final List<Page> pages) { public Observable<Page> getRemainingImageUrlsFromPageList(final List<Page> pages) {
return Observable.from(pages) return Observable.from(pages)
.filter(page -> page.getImageUrl() == null) .filter(page -> page.getImageUrl() == null)
.buffer(getNumberOfConcurrentImageDownloads()) .window(getNumberOfConcurrentPageDownloads())
.concatMap(batchedPages -> { .concatMap(batchedPages ->
List<Observable<Page>> pageObservable = new ArrayList<>(); batchedPages.concatMap(this::getImageUrlFromPage)
for (Page page : batchedPages) { );
pageObservable.add(getImageUrlFromPage(page));
}
return Observable.merge(pageObservable);
});
} }
private Observable<Page> getImageUrlFromPage(final Page page) { private Observable<Page> getImageUrlFromPage(final Page page) {

View file

@ -6,27 +6,29 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.bumptech.glide.Glide; import com.davemorrissey.labs.subscaleview.ImageSource;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView; import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Page; import eu.kanade.mangafeed.data.models.Page;
import eu.kanade.mangafeed.ui.activity.ReaderActivity; import eu.kanade.mangafeed.ui.activity.ReaderActivity;
import eu.kanade.mangafeed.util.MangaImageRegionDecoder;
import eu.kanade.mangafeed.util.PageFileTarget;
public class ReaderPageFragment extends Fragment { public class ReaderPageFragment extends Fragment {
public static final String URL_ARGUMENT_KEY = "UrlArgumentKey"; public static final String URL_ARGUMENT_KEY = "UrlArgumentKey";
private SubsamplingScaleImageView imageView; @Bind(R.id.page_image_view) SubsamplingScaleImageView imageView;
@Bind(R.id.progress) ProgressBar progressBar;
private String mUrl; private String imagePath;
public static ReaderPageFragment newInstance(Page page) { public static ReaderPageFragment newInstance(Page page) {
ReaderPageFragment newInstance = new ReaderPageFragment(); ReaderPageFragment newInstance = new ReaderPageFragment();
Bundle arguments = new Bundle(); Bundle arguments = new Bundle();
arguments.putString(URL_ARGUMENT_KEY, page.getImageUrl()); arguments.putString(URL_ARGUMENT_KEY, page.getImagePath());
newInstance.setArguments(arguments); newInstance.setArguments(arguments);
return newInstance; return newInstance;
} }
@ -40,39 +42,42 @@ public class ReaderPageFragment extends Fragment {
Bundle arguments = getArguments(); Bundle arguments = getArguments();
if (arguments != null) { if (arguments != null) {
if (arguments.containsKey(URL_ARGUMENT_KEY)) { if (arguments.containsKey(URL_ARGUMENT_KEY)) {
mUrl = arguments.getString(URL_ARGUMENT_KEY); imagePath = arguments.getString(URL_ARGUMENT_KEY);
} }
} }
} }
public void setPage(Page page) { public void setPage(Page page) {
if (!page.getImageUrl().equals(mUrl)) { if (!page.getImageUrl().equals(imagePath)) {
mUrl = page.getImageUrl(); imagePath = page.getImagePath();
loadImage(); loadImage();
} }
} }
private void loadImage() { private void loadImage() {
if (mUrl != null) { if (imagePath != null) {
Glide.with(getActivity()) progressBar.setVisibility(View.GONE);
.load(mUrl) imageView.setImage(ImageSource.uri(imagePath).tilingDisabled());
.downloadOnly(new PageFileTarget(imageView));
} }
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
imageView = (SubsamplingScaleImageView)inflater.inflate(R.layout.fragment_page, container, false); View view = inflater.inflate(R.layout.fragment_page, container, false);
ButterKnife.bind(this, view);
imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED); imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED);
imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE); imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE); imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE);
imageView.setOnTouchListener((view, motionEvent) -> imageView.setOnTouchListener((v, motionEvent) ->
((ReaderActivity) getActivity()).getViewPager().onImageTouch(motionEvent)); ((ReaderActivity) getActivity()).getViewPager().onImageTouch(motionEvent));
progressBar.setVisibility(View.VISIBLE);
loadImage(); loadImage();
return imageView; return view;
} }
} }

View file

@ -1,36 +0,0 @@
package eu.kanade.mangafeed.util;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.ViewTarget;
import com.davemorrissey.labs.subscaleview.ImageSource;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
import java.io.File;
import eu.kanade.mangafeed.R;
public class PageFileTarget extends ViewTarget<SubsamplingScaleImageView, File> {
public PageFileTarget(SubsamplingScaleImageView view) {
super(view);
}
@Override
public void onLoadCleared(Drawable placeholder) {
view.setImage(ImageSource.resource(R.drawable.ic_action_refresh));
}
@Override
public void onLoadStarted(Drawable placeholder) {
view.setImage(ImageSource.resource(R.drawable.ic_action_refresh));
}
@Override
public void onResourceReady(File resource, GlideAnimation<? super File> glideAnimation) {
view.setImage(ImageSource.uri(Uri.fromFile(resource))
.tilingDisabled());
}
}

View file

@ -1,6 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone" />
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView xmlns:android="http://schemas.android.com/apk/res/android" <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/page_image_view" /> android:id="@+id/page_image_view" />
</FrameLayout>