首页 > 开发 > Java > 正文

RxJava2.x+ReTrofit2.x多线程下载文件的示例代码

2024-07-13 10:11:40
字体:
来源:转载
供稿:网友

写在前面:

接到公司需求:要做一个apk升级的功能,原理其实很简单,百度也一大堆例子,可大部分都是用框架,要么就是HttpURLConnection,实在是不想这么干。正好看了两天的RxJava2.x+ReTrofit2.x,据说这俩框架是目前最火的异步请求框架了。固本文使用RxJava2.x+ReTrofit2.x实现多线程下载文件的功能。
如果对RxJava2.x+ReTrofit2.x不太了解的请先去看相关的文档。
大神至此请无视。

思路分析:

思路及其简洁明了,主要分为以下四步

1.获取服务器文件大小.
2.根据文件大小规划线程数量.
3.根据下载内容合并为完整文件.
4.调用安装,安装apk.
功能实现

来,接下来是你们最喜欢的撸代码环节

1.首先看引用

  compile 'io.reactivex:rxjava:latest.release'  compile 'io.reactivex:rxandroid:latest.release'  //network - squareup  compile 'com.squareup.retrofit2:retrofit:latest.release'  compile 'com.squareup.retrofit2:adapter-rxjava:latest.release'  compile 'com.squareup.okhttp3:okhttp:latest.release'  compile 'com.squareup.okhttp3:logging-interceptor:latest.release'

2.构造一个下载接口DownloadService.class

public interface DownloadService {  @Streaming  @GET  //downParam下载参数,传下载区间使用  //url 下载链接  Observable<ResponseBody> download(@Header("RANGE") String downParam,@Url String url);}

3.为了使用方便封装了一个RetrofitHelper.class,主要用于:

a)实例化OkHttpClient和Retrofit.

  public RetrofitHelper(String url, DownloadProgressListener listener) {    DownloadProgressInterceptor interceptor = new DownloadProgressInterceptor(listener);    OkHttpClient client = new OkHttpClient.Builder()        .addInterceptor(interceptor)        .retryOnConnectionFailure(true)        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)        .build();    retrofit = new Retrofit.Builder()        .baseUrl(url)        .client(client)        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())        .build();  }

b)封装下载方法,本次下载我使用的是三个下载线程,并没有动态分配,各位可以根据自己的需求去动态分配线程个数

 public Observable download(@NonNull final long start, @NonNull final long end, @NonNull final String url, final File file, final Subscriber subscriber) {    String str = "";    if (end == -1) {      str = "";    } else {      str = end + "";    }    return retrofit.create(DownloadService.class).download("bytes=" + start + "-" + str, url).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).map(new Func1<ResponseBody, ResponseBody>() {      @Override      public ResponseBody call(ResponseBody responseBody) {        return responseBody;      }    }).observeOn(Schedulers.computation()).doOnNext(new Action1<ResponseBody>() {      @Override      public void call(ResponseBody responseBody) {        //第一次请求全部文件长度        if (end == -1) {          try {            RandomAccessFile randomFile = new RandomAccessFile(file, "rw");            randomFile.setLength(responseBody.contentLength());            long one = responseBody.contentLength() / 3;            download(0, one, url, file, subscriber).mergeWith(download(one, one * 2, url, file, subscriber)).mergeWith(download(one * 2, responseBody.contentLength(), url, file, subscriber)).subscribe(subscriber);          } catch (IOException e) {            e.printStackTrace();          }        } else {          FileUtils fileUtils = new FileUtils();          fileUtils.writeFile(start, end, responseBody.byteStream(), file);        }      }    }).subscribeOn(AndroidSchedulers.mainThread());  }

 4.调用下载

注:调用下载在MainAcitivity中进行,为了直观我们封装了进度拦截器以方便实现进度显示,但是本篇不在叙述进度拦截器的实现过程,如有需要可以留言。

a)实现监听对象

subscriber = new Subscriber() {      @Override      public void onCompleted() {        Log.e("MainActivity", "onCompleted下下载完成");//        Toast.makeText(MainActivity.this, "onCompleted下下载完成", Toast.LENGTH_LONG).show();        installAPK("mnt/sdcard/aaaaaaaaa.apk");      }      @Override      public void onError(Throwable e) {        e.printStackTrace();        Log.e("MainActivity", "onError: " + e.getMessage());      }      @Override      public void onNext(Object o) {      }    };

 b)调用封装的RetrofitHelper实现下载

 RetrofitHelper RetrofitHelper = new RetrofitHelper("http://gdown.baidu.com/data/wisegame/0904344dee4a2d92/", new DownloadProgressListener() {      @Override      public void update(long bytesRead, long contentLength, boolean done) {        SharedPF.getSharder().setLong("update", bytesRead);        pro.setProgress((int) ((double) bytesRead / contentLength * 100));        temp++;        if (temp <= 1) {          Log.e("MainActivity", "update" + bytesRead + "");        }      }    });    RetrofitHelper.download(0, -1, "QQ_718.apk", new File("mnt/sdcard/", "aaaaaaaaa.apk"), subscriber).subscribe(new Subscriber() {      @Override      public void onCompleted() {      }      @Override      public void onError(Throwable e) {      }      @Override      public void onNext(Object o) {      }    });  }

 注:最后贴一个apk安装的方法

  // 安装APK  public void installAPK(String filePath) {    Intent intent = new Intent();    intent.setAction("android.intent.action.VIEW");    intent.addCategory("android.intent.category.DEFAULT");    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 广播里面操作需要加上这句,存在于一个独立的栈里    intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");    mainActivity.startActivity(intent);  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表