package zlc.season.rxdownload2.entity; import java.util.Map; import java.util.concurrent.Semaphore; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Action; import io.reactivex.functions.Consumer; import io.reactivex.processors.FlowableProcessor; import io.reactivex.schedulers.Schedulers; import zlc.season.rxdownload2.RxDownload; import zlc.season.rxdownload2.db.DataBaseHelper; import zlc.season.rxdownload2.function.Constant; import static zlc.season.rxdownload2.entity.DownloadFlag.WAITING; import static zlc.season.rxdownload2.function.DownloadEventFactory.completed; import static zlc.season.rxdownload2.function.DownloadEventFactory.failed; import static zlc.season.rxdownload2.function.DownloadEventFactory.normal; import static zlc.season.rxdownload2.function.DownloadEventFactory.paused; import static zlc.season.rxdownload2.function.DownloadEventFactory.started; import static zlc.season.rxdownload2.function.DownloadEventFactory.waiting; import static zlc.season.rxdownload2.function.Utils.createProcessor; import static zlc.season.rxdownload2.function.Utils.deleteFiles; import static zlc.season.rxdownload2.function.Utils.dispose; import static zlc.season.rxdownload2.function.Utils.formatStr; import static zlc.season.rxdownload2.function.Utils.getFiles; import static zlc.season.rxdownload2.function.Utils.log; /** * Author: Season(ssseasonnn@gmail.com) * Date: 2017/2/24 * <p> * SingleMission, only one url. */ public class SingleMission extends DownloadMission { protected DownloadStatus status; protected Disposable disposable; private DownloadBean bean; private String missionId; private Observer<DownloadStatus> observer; public SingleMission(RxDownload rxdownload, DownloadBean bean) { super(rxdownload); this.bean = bean; } public SingleMission(RxDownload rxDownload, DownloadBean bean, String missionId, Observer<DownloadStatus> observer) { super(rxDownload); this.bean = bean; this.missionId = missionId; this.observer = observer; } public SingleMission(SingleMission other, Observer<DownloadStatus> observer) { super(other.rxdownload); this.bean = other.getBean(); this.missionId = other.getMissionId(); this.observer = observer; } @Override public String getUrl() { return bean.getUrl(); } @Override public void init(Map<String, DownloadMission> missionMap, Map<String, FlowableProcessor<DownloadEvent>> processorMap) { DownloadMission mission = missionMap.get(getUrl()); if (mission == null) { missionMap.put(getUrl(), this); } else { if (mission.isCanceled()) { missionMap.put(getUrl(), this); } else { throw new IllegalArgumentException(formatStr(Constant.DOWNLOAD_URL_EXISTS, getUrl())); } } this.processor = createProcessor(getUrl(), processorMap); } @Override public void insertOrUpdate(DataBaseHelper dataBaseHelper) { if (dataBaseHelper.recordNotExists(getUrl())) { dataBaseHelper.insertRecord(bean, WAITING, missionId); } else { dataBaseHelper.updateRecord(getUrl(), WAITING, missionId); } } @Override public void sendWaitingEvent(DataBaseHelper dataBaseHelper) { processor.onNext(waiting(dataBaseHelper.readStatus(getUrl()))); } @Override public void start(final Semaphore semaphore) throws InterruptedException { if (isCanceled()) { return; } semaphore.acquire(); if (isCanceled()) { semaphore.release(); return; } disposable = rxdownload.download(bean) .subscribeOn(Schedulers.io()) .doOnSubscribe(new Consumer<Disposable>() { @Override public void accept(Disposable disposable) throws Exception { if (observer != null) { observer.onSubscribe(disposable); } } }) .doFinally(new Action() { @Override public void run() throws Exception { log("finally and release..."); setCanceled(true); semaphore.release(); } }) .subscribe(new Consumer<DownloadStatus>() { @Override public void accept(DownloadStatus value) throws Exception { status = value; processor.onNext(started(value)); if (observer != null) { observer.onNext(value); } } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { processor.onNext(failed(status, throwable)); if (observer != null) { observer.onError(throwable); } } }, new Action() { @Override public void run() throws Exception { processor.onNext(completed(status)); setCompleted(true); if (observer != null) { observer.onComplete(); } } }); } @Override public void pause(DataBaseHelper dataBaseHelper) { dispose(disposable); setCanceled(true); if (processor != null && !isCompleted()) { processor.onNext(paused(dataBaseHelper.readStatus(getUrl()))); } } @Override public void delete(DataBaseHelper dataBaseHelper, boolean deleteFile) { pause(dataBaseHelper); if (processor != null) { processor.onNext(normal(null)); } if (deleteFile) { DownloadRecord record = dataBaseHelper.readSingleRecord(getUrl()); if (record != null) { deleteFiles(getFiles(record.getSaveName(), record.getSavePath())); } } dataBaseHelper.deleteRecord(getUrl()); } private String getMissionId() { return missionId; } private Observer<DownloadStatus> getObserver() { return observer; } private DownloadBean getBean() { return bean; } }