Cache chapter images from presenter with glide.
This commit is contained in:
parent
fefc6ba0e9
commit
ef7613f7ad
10 changed files with 93 additions and 71 deletions
|
@ -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(
|
||||||
|
|
|
@ -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 + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,21 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout
|
||||||
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" />
|
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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/page_image_view" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
Reference in a new issue