Name Last Update
.idea Loading commit data...
app Loading commit data...
gradle/wrapper Loading commit data...
.gitignore Loading commit data...
README.md Loading commit data...
build.gradle Loading commit data...
gradle.properties Loading commit data...
gradlew Loading commit data...
gradlew.bat Loading commit data...
settings.gradle Loading commit data...

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来通知页面刷新