Better handling of loading progress and image load.
This commit is contained in:
parent
d26049155c
commit
e160f53bb2
11 changed files with 108 additions and 87 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Reference in a new issue