Better handling of loading progress and image load.

This commit is contained in:
inorichi 2015-10-28 17:20:00 +01:00
parent d26049155c
commit e160f53bb2
11 changed files with 108 additions and 87 deletions

View file

@ -1,6 +1,7 @@
package eu.kanade.mangafeed.data.models; package eu.kanade.mangafeed.data.models;
import eu.kanade.mangafeed.data.helpers.NetworkHelper; import eu.kanade.mangafeed.data.helpers.NetworkHelper;
import rx.subjects.PublishSubject;
public class Page implements NetworkHelper.ProgressListener { public class Page implements NetworkHelper.ProgressListener {
@ -8,12 +9,16 @@ public class Page implements NetworkHelper.ProgressListener {
private String url; private String url;
private String imageUrl; private String imageUrl;
private String imagePath; private String imagePath;
private int status; private transient int status;
private int progress; private transient int progress;
public static final int DOWNLOAD = 0; private transient PublishSubject<Integer> statusSubject;
public static final int READY = 1;
public static final int ERROR = 2; public static final int QUEUE = 0;
public static final int LOAD_PAGE = 1;
public static final int DOWNLOAD_IMAGE = 2;
public static final int READY = 3;
public static final int ERROR = 4;
public Page(int pageNumber, String url, String imageUrl, String imagePath) { public Page(int pageNumber, String url, String imageUrl, String imagePath) {
this.pageNumber = pageNumber; this.pageNumber = pageNumber;
@ -56,6 +61,8 @@ public class Page implements NetworkHelper.ProgressListener {
public void setStatus(int status) { public void setStatus(int status) {
this.status = status; this.status = status;
if (statusSubject != null)
statusSubject.onNext(status);
} }
public int getProgress() { public int getProgress() {
@ -76,4 +83,8 @@ public class Page implements NetworkHelper.ProgressListener {
progress = (int) ((100 * bytesRead) / contentLength); progress = (int) ((100 * bytesRead) / contentLength);
} }
public void setStatusSubject(PublishSubject<Integer> subject) {
this.statusSubject = subject;
}
} }

View file

@ -47,10 +47,6 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
restartableReplay(GET_PAGE_IMAGES, restartableReplay(GET_PAGE_IMAGES,
this::getPageImagesObservable, this::getPageImagesObservable,
(view, page) -> { (view, page) -> {
view.onNextPage(page);
if (page.getPageNumber() == savedSelectedPage) {
view.setCurrentPage(savedSelectedPage);
}
}, },
(view, error) -> Timber.e("An error occurred while downloading an image")); (view, error) -> Timber.e("An error occurred while downloading an image"));
} }

View file

@ -80,7 +80,6 @@ public abstract class Source extends BaseSource {
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)
.doOnNext(page -> page.setStatus(Page.DOWNLOAD))
.window(overrideNumberOfConcurrentPageDownloads()) .window(overrideNumberOfConcurrentPageDownloads())
.concatMap(batchedPages -> .concatMap(batchedPages ->
batchedPages.concatMap(this::getImageUrlFromPage) batchedPages.concatMap(this::getImageUrlFromPage)
@ -88,6 +87,7 @@ public abstract class Source extends BaseSource {
} }
private Observable<Page> getImageUrlFromPage(final Page page) { private Observable<Page> getImageUrlFromPage(final Page page) {
page.setStatus(Page.LOAD_PAGE);
return mNetworkService return mNetworkService
.getStringResponse(overrideRemainingPagesUrl(page.getUrl()), mRequestHeaders, null) .getStringResponse(overrideRemainingPagesUrl(page.getUrl()), mRequestHeaders, null)
.flatMap(unparsedHtml -> Observable.just(parseHtmlToImageUrl(unparsedHtml))) .flatMap(unparsedHtml -> Observable.just(parseHtmlToImageUrl(unparsedHtml)))
@ -108,7 +108,7 @@ public abstract class Source extends BaseSource {
return obs; return obs;
if (!mCacheManager.isImageInCache(page.getImageUrl())) { if (!mCacheManager.isImageInCache(page.getImageUrl())) {
page.setStatus(Page.DOWNLOAD); page.setStatus(Page.DOWNLOAD_IMAGE);
obs = cacheImage(page); obs = cacheImage(page);
} }

View file

@ -71,10 +71,6 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
viewer.onPageListReady(pages); viewer.onPageListReady(pages);
} }
public void onNextPage(Page page) {
viewer.onNextPage(page);
}
public void onPageChanged(int currentPage, int totalPages) { public void onPageChanged(int currentPage, int totalPages) {
String page = currentPage + "/" + totalPages; String page = currentPage + "/" + totalPages;
pageNumber.setText(page); pageNumber.setText(page);

View file

@ -38,13 +38,4 @@ public class ReaderPageAdapter extends SmartFragmentStatePagerAdapter {
notifyDataSetChanged(); notifyDataSetChanged();
} }
public void replacePage(int position, Page page) {
pages.set(position, page);
ReaderPageFragment fragment = (ReaderPageFragment)getRegisteredFragment(position);
if (fragment != null) {
fragment.replacePage(page);
}
}
} }

View file

@ -24,6 +24,7 @@ import rx.Observable;
import rx.Subscription; import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
public class ReaderPageFragment extends Fragment { public class ReaderPageFragment extends Fragment {
@ -35,6 +36,7 @@ public class ReaderPageFragment extends Fragment {
private Page page; private Page page;
private Subscription progressSubscription; private Subscription progressSubscription;
private Subscription statusSubscription;
public static ReaderPageFragment newInstance(Page page) { public static ReaderPageFragment newInstance(Page page) {
ReaderPageFragment fragment = new ReaderPageFragment(); ReaderPageFragment fragment = new ReaderPageFragment();
@ -48,35 +50,6 @@ public class ReaderPageFragment extends Fragment {
setRetainInstance(true); setRetainInstance(true);
} }
public void replacePage(Page page) {
unsubscribeProgress();
this.page = page;
loadImage();
}
public void setPage(Page page) {
this.page = page;
}
private void loadImage() {
if (page == null)
return;
switch (page.getStatus()) {
case (Page.READY):
imageView.setImage(ImageSource.uri(page.getImagePath()).tilingDisabled());
progressContainer.setVisibility(View.GONE);
break;
case (Page.DOWNLOAD):
progressContainer.setVisibility(View.VISIBLE);
break;
case (Page.ERROR):
progressContainer.setVisibility(View.GONE);
errorText.setVisibility(View.VISIBLE);
}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page, container, false); View view = inflater.inflate(R.layout.fragment_page, container, false);
@ -88,42 +61,111 @@ public class ReaderPageFragment extends Fragment {
imageView.setOnTouchListener((v, motionEvent) -> imageView.setOnTouchListener((v, motionEvent) ->
((ReaderActivity) getActivity()).onImageTouch(motionEvent)); ((ReaderActivity) getActivity()).onImageTouch(motionEvent));
observeProgress();
loadImage();
return view; return view;
} }
public void onStart() {
super.onStart();
observeStatus();
}
@Override @Override
public void onStop() { public void onStop() {
super.onStop();
unsubscribeProgress(); unsubscribeProgress();
unsubscribeStatus();
super.onStop();
}
public void setPage(Page page) {
this.page = page;
}
private void showImage() {
if (page == null || page.getImagePath() == null)
return;
imageView.setImage(ImageSource.uri(page.getImagePath()));
progressContainer.setVisibility(View.GONE);
}
private void showDownloading() {
progressText.setVisibility(View.VISIBLE);
}
private void showLoading() {
progressText.setVisibility(View.VISIBLE);
progressText.setText(R.string.downloading);
}
private void showError() {
progressContainer.setVisibility(View.GONE);
errorText.setVisibility(View.VISIBLE);
}
private void processStatus(int status) {
switch (status) {
case Page.READY:
showImage();
unsubscribeProgress();
unsubscribeStatus();
break;
case Page.LOAD_PAGE:
showLoading();
break;
case Page.DOWNLOAD_IMAGE:
showDownloading();
break;
case Page.ERROR:
showError();
unsubscribeProgress();
break;
}
}
private void observeStatus() {
if (page == null)
return;
if (page.getStatus() == Page.READY) {
showImage();
} else {
processStatus(page.getStatus());
PublishSubject<Integer> statusSubject = PublishSubject.create();
page.setStatusSubject(statusSubject);
observeProgress();
statusSubscription = statusSubject
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::processStatus);
}
} }
private void observeProgress() { private void observeProgress() {
if (page == null || page.getStatus() != Page.DOWNLOAD)
return;
progressSubscription = Observable.interval(75, TimeUnit.MILLISECONDS) progressSubscription = Observable.interval(75, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(tick -> { .subscribe(tick -> {
if (page.getProgress() == 0) { if (page.getProgress() != 0)
progressText.setText(R.string.downloading); progressText.setText(
} getString(R.string.download_progress, page.getProgress()));
else if (page.getProgress() == 100) {
progressContainer.setVisibility(View.GONE);
unsubscribeProgress();
}
else {
progressText.setText(getString(R.string.download_progress, page.getProgress()));
}
}); });
} }
private void unsubscribeStatus() {
if (statusSubscription != null) {
page.setStatusSubject(null);
statusSubscription.unsubscribe();
statusSubscription = null;
}
}
private void unsubscribeProgress() { private void unsubscribeProgress() {
if (progressSubscription != null) if (progressSubscription != null) {
progressSubscription.unsubscribe(); progressSubscription.unsubscribe();
progressSubscription = null;
}
} }
} }

View file

@ -58,11 +58,6 @@ public class VerticalViewer extends BaseViewer {
updatePageNumber(); updatePageNumber();
} }
@Override
public void onNextPage(Page page) {
adapter.replacePage(getPosFromPage(page), page);
}
@Override @Override
public boolean onImageTouch(MotionEvent motionEvent) { public boolean onImageTouch(MotionEvent motionEvent) {
return false; return false;

View file

@ -33,11 +33,6 @@ public class WebtoonViewer extends BaseViewer {
return adapter.getItemCount(); return adapter.getItemCount();
} }
@Override
public void onNextPage(Page page) {
adapter.setPage(getPosFromPage(page), page);
}
@Override @Override
public void onPageListReady(List<Page> pages) { public void onPageListReady(List<Page> pages) {
adapter.setPages(pages); adapter.setPages(pages);

View file

@ -33,6 +33,5 @@ public abstract class BaseViewer {
public abstract int getTotalPages(); public abstract int getTotalPages();
public abstract void onPageListReady(List<Page> pages); public abstract void onPageListReady(List<Page> pages);
public abstract void onNextPage(Page page);
public abstract boolean onImageTouch(MotionEvent motionEvent); public abstract boolean onImageTouch(MotionEvent motionEvent);
} }

View file

@ -71,11 +71,6 @@ public abstract class ViewPagerViewer extends BaseViewer {
updatePageNumber(); updatePageNumber();
} }
@Override
public void onNextPage(Page page) {
adapter.replacePage(getPosFromPage(page), page);
}
@Override @Override
public boolean onImageTouch(MotionEvent motionEvent) { public boolean onImageTouch(MotionEvent motionEvent) {
return viewPager.onImageTouch(motionEvent); return viewPager.onImageTouch(motionEvent);

View file

@ -25,6 +25,7 @@
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:id="@+id/progress_text" android:id="@+id/progress_text"
android:layout_gravity="center" android:layout_gravity="center"
android:visibility="invisible"
android:textSize="16sp" /> android:textSize="16sp" />
</LinearLayout> </LinearLayout>