当前位置: 移动技术网 > IT编程>开发语言>Java > RxJava2.x+ReTrofit2.x多线程下载文件的示例代码

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

2019年07月19日  | 移动技术网IT编程  | 我要评论

写在前面:

接到公司需求:要做一个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);
  }

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网