README.md 4.95 KB

DownloadFile

Android OkHttp 下载多个文件 断点下载

介绍

demo的主要逻辑是,利用okhttp 和 RxJava 在子线程中下载文件,通关观察者模式监听下载的进度,再回调到主线程中,然后利用EventBus 通知页面刷新,更新进度。

step1 导入依赖库

// OKHttp RxJava
    implementation 'com.squareup.okhttp3:okhttp:3.6.0'
    implementation 'io.reactivex.rxjava2:rxjava:2.1.3'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    // eventbus
    implementation 'org.greenrobot:eventbus:3.0.0'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    implementation 'com.google.code.gson:gson:2.8.1'
    //数据保存
    implementation 'org.greenrobot:greendao:3.2.2'

step 2 定义下载bean

```Java DownloadInfo

step 3 DownLoadService 开启一个服务,进行删除,下载,暂停,等待等操作

step 4 下载管理类 也是主要的内容 (DownloadManager)具体的数据保存方法

      public void download(final DownloadInfo downloadInfo) {
             List<DownloadInfo> list = MyApplication.getInstances().getDaoSession().loadAll(DownloadInfo.class);
             downWait.clear();
             downWait = list;
             if (currentDownInfo != null) pauseDownload(currentDownInfo, true);
             if (downCalls.containsKey(downloadInfo.getUrl())) downCalls.remove(downloadInfo.getUrl());
             Observable.just(downloadInfo.getUrl())
                     .filter(new Predicate<String>() { // 过滤 call的map中已经有了,就证明正在下载,则这次不下载
                         @Override
                         public boolean test(String s) {
                             boolean flag = downCalls.containsKey(s);
                             if (flag) {
                                 // 如果已经在下载,并且不是暂停的数据,查找下一个文件进行下载
                                 downNext();
                                 return false;
                             } else {
                                 // 判断如果正在下载的个数达到最大限制,存到等下下载列表中
                                 return true;
                             }
                         }
                     })
                     .flatMap(new Function<String, ObservableSource<?>>() { // 生成 DownloadInfo
                         @Override
                         public ObservableSource<?> apply(String s) {
                             return Observable.just(createDownInfo(downloadInfo));
                         }
                     })
                     .map(new Function<Object, DownloadInfo>() { // 如果已经下载,重新命名
                         @Override
                         public DownloadInfo apply(Object o) {
                             return getRealFileName((DownloadInfo) o);
                         }
                     })
                     .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() { // 下载
                         @Override
                         public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) {
                             currentDownInfo = downloadInfo;
                             return Observable.create(new DownloadSubscribe(downloadInfo));
                         }
                     })
                     .observeOn(AndroidSchedulers.mainThread()) // 在主线程中回调
                     .subscribeOn(Schedulers.io()) //  在子线程中执行
                     .subscribe(new DownloadLimitObserver()); //  添加观察者,监听下载进度
         }

这里用到的是Rxjava,第一步filter,过滤下载,已经下载的url再点击下载是不会另起下载任务的;第二步flatMap,通过url生成Bean类,这个按需求来设计,也可以直接传一个Bean进来也是可以的;第三步map,如果这个文件已经下载了,再次下载重新命名文件,这也是根据需求改变,如果下载过的文件不需要下载,这就可以省了;第四步flatMap,去下载具体去看下载方法;剩下的就是切换线程和添加观察者了。

step4 观察者

public class DownloadObserver implements Observer<DownloadInfo> {

    public Disposable d;//可以用于取消注册的监听者
    public DownloadInfo downloadInfo;

    @Override
    public void onSubscribe(Disposable d) {
        this.d = d;
    }

    @Override
    public void onNext(DownloadInfo value) {
        this.downloadInfo = value;
        downloadInfo.setDownloadStatus(DownloadInfo.DOWNLOAD);
        EventBus.getDefault().post(downloadInfo);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {
        if (downloadInfo != null){
            downloadInfo.setDownloadStatus(DownloadInfo.DOWNLOAD_OVER);
            EventBus.getDefault().post(downloadInfo);
        }
    }
}

这里是用到EventBus来通知页面刷新