mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-21 20:47:03 -05:00
Update number of downloaded images in the queue, and improve the way the view refreshes the data
This commit is contained in:
parent
7c37262a9f
commit
ceb56e2c8a
6 changed files with 88 additions and 27 deletions
|
@ -77,7 +77,6 @@ public class DownloadManager {
|
||||||
.subscribe(threadsNumber::onNext);
|
.subscribe(threadsNumber::onNext);
|
||||||
|
|
||||||
downloadsSubscription = downloadsQueueSubject
|
downloadsSubscription = downloadsQueueSubject
|
||||||
.observeOn(Schedulers.newThread())
|
|
||||||
.lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber))
|
.lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber))
|
||||||
.onBackpressureBuffer()
|
.onBackpressureBuffer()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -167,6 +166,8 @@ public class DownloadManager {
|
||||||
Observable.just(download.pages);
|
Observable.just(download.pages);
|
||||||
|
|
||||||
return pageListObservable
|
return pageListObservable
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.doOnNext(pages -> download.downloadedImages = 0)
|
||||||
.doOnNext(pages -> download.setStatus(Download.DOWNLOADING))
|
.doOnNext(pages -> download.setStatus(Download.DOWNLOADING))
|
||||||
// Get all the URLs to the source images, fetch pages if necessary
|
// Get all the URLs to the source images, fetch pages if necessary
|
||||||
.flatMap(pageList -> Observable.merge(
|
.flatMap(pageList -> Observable.merge(
|
||||||
|
@ -174,6 +175,7 @@ public class DownloadManager {
|
||||||
download.source.getRemainingImageUrlsFromPageList(pageList)))
|
download.source.getRemainingImageUrlsFromPageList(pageList)))
|
||||||
// Start downloading images, consider we can have downloaded images already
|
// Start downloading images, consider we can have downloaded images already
|
||||||
.concatMap(page -> getDownloadedImage(page, download.source, download.directory))
|
.concatMap(page -> getDownloadedImage(page, download.source, download.directory))
|
||||||
|
.doOnNext(p -> download.downloadedImages++)
|
||||||
// Do after download completes
|
// Do after download completes
|
||||||
.doOnCompleted(() -> onDownloadCompleted(download))
|
.doOnCompleted(() -> onDownloadCompleted(download))
|
||||||
.toList()
|
.toList()
|
||||||
|
@ -363,6 +365,11 @@ public class DownloadManager {
|
||||||
|
|
||||||
public void stopDownloads() {
|
public void stopDownloads() {
|
||||||
destroySubscriptions();
|
destroySubscriptions();
|
||||||
|
for (Download download : queue.get()) {
|
||||||
|
if (download.getStatus() == Download.DOWNLOADING) {
|
||||||
|
download.setStatus(Download.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
|
|
|
@ -14,6 +14,7 @@ public class Download {
|
||||||
public File directory;
|
public File directory;
|
||||||
|
|
||||||
public transient volatile int totalProgress;
|
public transient volatile int totalProgress;
|
||||||
|
public transient volatile int downloadedImages;
|
||||||
private transient volatile int status;
|
private transient volatile int status;
|
||||||
|
|
||||||
private transient PublishSubject<Download> statusSubject;
|
private transient PublishSubject<Download> statusSubject;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.os.Bundle;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -76,12 +75,17 @@ public class DownloadQueuePresenter extends BasePresenter<DownloadQueueFragment>
|
||||||
unsubscribeProgress(download);
|
unsubscribeProgress(download);
|
||||||
unsubscribePagesStatus(download);
|
unsubscribePagesStatus(download);
|
||||||
view.updateProgress(download);
|
view.updateProgress(download);
|
||||||
|
view.updateDownloadedPages(download);
|
||||||
|
break;
|
||||||
|
case Download.ERROR:
|
||||||
|
unsubscribeProgress(download);
|
||||||
|
unsubscribePagesStatus(download);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void observeProgress(Download download, DownloadQueueFragment view) {
|
private void observeProgress(Download download, DownloadQueueFragment view) {
|
||||||
Subscription subscription = Observable.interval(75, TimeUnit.MILLISECONDS, Schedulers.newThread())
|
Subscription subscription = Observable.interval(50, TimeUnit.MILLISECONDS, Schedulers.newThread())
|
||||||
.flatMap(tick -> Observable.from(download.pages)
|
.flatMap(tick -> Observable.from(download.pages)
|
||||||
.map(Page::getProgress)
|
.map(Page::getProgress)
|
||||||
.reduce((x, y) -> x + y))
|
.reduce((x, y) -> x + y))
|
||||||
|
@ -93,26 +97,31 @@ public class DownloadQueuePresenter extends BasePresenter<DownloadQueueFragment>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Avoid leaking subscriptions
|
||||||
|
Subscription oldSubscription = progressSubscriptions.remove(download);
|
||||||
|
if (oldSubscription != null) oldSubscription.unsubscribe();
|
||||||
|
|
||||||
progressSubscriptions.put(download, subscription);
|
progressSubscriptions.put(download, subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void observePagesStatus(Download download, DownloadQueueFragment view) {
|
private void observePagesStatus(Download download, DownloadQueueFragment view) {
|
||||||
PublishSubject<Integer> pageStatusSubject = PublishSubject.create();
|
PublishSubject<Integer> pageStatusSubject = PublishSubject.create();
|
||||||
for (Page page : download.pages)
|
for (Page page : download.pages) {
|
||||||
|
if (page.getStatus() != Page.READY)
|
||||||
page.setStatusSubject(pageStatusSubject);
|
page.setStatusSubject(pageStatusSubject);
|
||||||
|
}
|
||||||
final AtomicInteger downloadedPages = new AtomicInteger(0);
|
|
||||||
|
|
||||||
Subscription subscription = pageStatusSubject
|
Subscription subscription = pageStatusSubject
|
||||||
.startWith(Observable.from(download.pages)
|
|
||||||
.filter(page -> page.getStatus() == Page.READY)
|
|
||||||
.map(page -> Page.READY))
|
|
||||||
.filter(status -> status == Page.READY)
|
.filter(status -> status == Page.READY)
|
||||||
.map(status -> downloadedPages.incrementAndGet())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(count -> {
|
.subscribe(status -> {
|
||||||
// TODO
|
view.updateDownloadedPages(download);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Avoid leaking subscriptions
|
||||||
|
Subscription oldSubscription = progressSubscriptions.remove(download);
|
||||||
|
if (oldSubscription != null) oldSubscription.unsubscribe();
|
||||||
|
|
||||||
pageStatusSubscriptions.put(download, subscription);
|
pageStatusSubscriptions.put(download, subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +132,10 @@ public class DownloadQueuePresenter extends BasePresenter<DownloadQueueFragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unsubscribePagesStatus(Download download) {
|
private void unsubscribePagesStatus(Download download) {
|
||||||
|
if (download.pages != null) {
|
||||||
for (Page page : download.pages)
|
for (Page page : download.pages)
|
||||||
page.setStatusSubject(null);
|
page.setStatusSubject(null);
|
||||||
|
}
|
||||||
|
|
||||||
Subscription subscription = pageStatusSubscriptions.remove(download);
|
Subscription subscription = pageStatusSubscriptions.remove(download);
|
||||||
if (subscription != null)
|
if (subscription != null)
|
||||||
|
@ -136,7 +147,6 @@ public class DownloadQueuePresenter extends BasePresenter<DownloadQueueFragment>
|
||||||
for (Page page : download.pages)
|
for (Page page : download.pages)
|
||||||
page.setStatusSubject(null);
|
page.setStatusSubject(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Subscription subscription : pageStatusSubscriptions.values()) {
|
for (Subscription subscription : pageStatusSubscriptions.values()) {
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package eu.kanade.mangafeed.ui.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.data.models.Download;
|
||||||
|
import eu.kanade.mangafeed.ui.holder.DownloadHolder;
|
||||||
|
import uk.co.ribot.easyadapter.EasyRecyclerAdapter;
|
||||||
|
|
||||||
|
public class DownloadAdapter extends EasyRecyclerAdapter<Download> {
|
||||||
|
|
||||||
|
public DownloadAdapter(Context context) {
|
||||||
|
super(context, DownloadHolder.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPositionForItem(Download item) {
|
||||||
|
return getItems() != null && getItems().size() > 0 ? getItems().indexOf(item) : -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ import android.support.v7.widget.RecyclerView;
|
||||||
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 android.widget.TextView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -14,16 +16,16 @@ import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.models.Download;
|
import eu.kanade.mangafeed.data.models.Download;
|
||||||
import eu.kanade.mangafeed.presenter.DownloadQueuePresenter;
|
import eu.kanade.mangafeed.presenter.DownloadQueuePresenter;
|
||||||
|
import eu.kanade.mangafeed.ui.adapter.DownloadAdapter;
|
||||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||||
import eu.kanade.mangafeed.ui.holder.DownloadHolder;
|
|
||||||
import nucleus.factory.RequiresPresenter;
|
import nucleus.factory.RequiresPresenter;
|
||||||
import uk.co.ribot.easyadapter.EasyRecyclerAdapter;
|
|
||||||
|
|
||||||
@RequiresPresenter(DownloadQueuePresenter.class)
|
@RequiresPresenter(DownloadQueuePresenter.class)
|
||||||
public class DownloadQueueFragment extends BaseRxFragment<DownloadQueuePresenter> {
|
public class DownloadQueueFragment extends BaseRxFragment<DownloadQueuePresenter> {
|
||||||
|
|
||||||
@Bind(R.id.download_list) RecyclerView downloadList;
|
@Bind(R.id.download_list) RecyclerView downloadList;
|
||||||
private EasyRecyclerAdapter<Download> adapter;
|
private LinearLayoutManager downloadListLayout;
|
||||||
|
private DownloadAdapter adapter;
|
||||||
|
|
||||||
public static DownloadQueueFragment newInstance() {
|
public static DownloadQueueFragment newInstance() {
|
||||||
return new DownloadQueueFragment();
|
return new DownloadQueueFragment();
|
||||||
|
@ -38,14 +40,15 @@ public class DownloadQueueFragment extends BaseRxFragment<DownloadQueuePresenter
|
||||||
|
|
||||||
setToolbarTitle(R.string.download_title);
|
setToolbarTitle(R.string.download_title);
|
||||||
|
|
||||||
downloadList.setLayoutManager(new LinearLayoutManager(getActivity()));
|
downloadListLayout = new LinearLayoutManager(getActivity());
|
||||||
|
downloadList.setLayoutManager(downloadListLayout);
|
||||||
createAdapter();
|
createAdapter();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAdapter() {
|
private void createAdapter() {
|
||||||
adapter = new EasyRecyclerAdapter<>(getActivity(), DownloadHolder.class);
|
adapter = new DownloadAdapter(getActivity());
|
||||||
downloadList.setAdapter(adapter);
|
downloadList.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,14 +56,32 @@ public class DownloadQueueFragment extends BaseRxFragment<DownloadQueuePresenter
|
||||||
adapter.setItems(downloads);
|
adapter.setItems(downloads);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO use a better approach
|
private View getDownloadRow(Download download) {
|
||||||
public void updateProgress(Download download) {
|
int first = downloadListLayout.findFirstVisibleItemPosition();
|
||||||
for (int i = 0; i < adapter.getItems().size(); i++) {
|
int last = downloadListLayout.findLastVisibleItemPosition();
|
||||||
if (adapter.getItem(i) == download) {
|
int pos = adapter.getPositionForItem(download);
|
||||||
adapter.notifyItemChanged(i);
|
|
||||||
break;
|
if (pos != -1 && pos >= first && pos <= last) {
|
||||||
|
return downloadListLayout.getChildAt(pos - first);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateProgress(Download download) {
|
||||||
|
View row = getDownloadRow(download);
|
||||||
|
if (row != null) {
|
||||||
|
ProgressBar progress = (ProgressBar) row.findViewById(R.id.download_progress);
|
||||||
|
if (progress.getMax() == 1) progress.setMax(download.pages.size() * 100);
|
||||||
|
progress.setProgress(download.totalProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateDownloadedPages(Download download) {
|
||||||
|
View row = getDownloadRow(download);
|
||||||
|
if (row != null) {
|
||||||
|
TextView progress = (TextView) row.findViewById(R.id.download_progress_text);
|
||||||
|
String progressText = download.downloadedImages + "/" + download.pages.size();
|
||||||
|
progress.setText(progressText);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,13 @@ public class DownloadHolder extends ItemViewHolder<Download> {
|
||||||
|
|
||||||
if (download.pages == null) {
|
if (download.pages == null) {
|
||||||
downloadProgress.setProgress(0);
|
downloadProgress.setProgress(0);
|
||||||
|
downloadProgress.setMax(1);
|
||||||
|
downloadProgressText.setText("");
|
||||||
} else {
|
} else {
|
||||||
downloadProgress.setMax(download.pages.size() * 100);
|
downloadProgress.setMax(download.pages.size() * 100);
|
||||||
downloadProgress.setProgress(download.totalProgress);
|
downloadProgress.setProgress(download.totalProgress);
|
||||||
|
String progressText = download.downloadedImages + "/" + download.pages.size();
|
||||||
|
downloadProgressText.setText(progressText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue