搜索
首页Javajava教程RxJava2.x与ReTrofit2.x多线程如何下载文件的实例

本篇文章主要介绍了RxJava2.x+ReTrofit2.x多线程下载文件的示例代码,具有一定的参考价值,有兴趣的可以了解一下

写在前面:

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

以上是RxJava2.x与ReTrofit2.x多线程如何下载文件的实例的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Java开发的哪些方面取决于平台?Java开发的哪些方面取决于平台?Apr 26, 2025 am 12:19 AM

JavadevelovermentIrelyPlatForm-DeTueTososeVeralFactors.1)JVMVariationsAffectPerformanceNandBehaviorAcroSsdifferentos.2)Nativelibrariesviajnijniiniininiinniinindrododerplatefform.3)

在不同平台上运行Java代码时是否存在性能差异?为什么?在不同平台上运行Java代码时是否存在性能差异?为什么?Apr 26, 2025 am 12:15 AM

Java代码在不同平台上运行时会有性能差异。1)JVM的实现和优化策略不同,如OracleJDK和OpenJDK。2)操作系统的特性,如内存管理和线程调度,也会影响性能。3)可以通过选择合适的JVM、调整JVM参数和代码优化来提升性能。

Java平台独立性有什么局限性?Java平台独立性有什么局限性?Apr 26, 2025 am 12:10 AM

Java'splatFormentenceHaslimitations不包括PerformanceOverhead,versionCompatibilityIsissues,挑战WithnativelibraryIntegration,Platform-SpecificFeatures,andjvminstallation/jvminstallation/jvmintenance/jeartenance.therefactorscomplicatorscomplicatethe“ writeOnce”

解释平台独立性和跨平台发展之间的差异。解释平台独立性和跨平台发展之间的差异。Apr 26, 2025 am 12:08 AM

PlatformIndependendecealLowsProgramStormonanyPlograwsStormanyPlatFormWithOutModification,而LileCross-PlatFormDevelopmentRequiredquiresMomePlatform-specificAdjustments.platFormIndependence,EneblesuniveByjava,EnablesuniversUniversAleversalexecutionbutmayCotutionButMayComproMisePerformance.cross.cross.cross-platformd

即时(JIT)汇编如何影响Java的性能和平台独立性?即时(JIT)汇编如何影响Java的性能和平台独立性?Apr 26, 2025 am 12:02 AM

JITcompilationinJavaenhancesperformancewhilemaintainingplatformindependence.1)Itdynamicallytranslatesbytecodeintonativemachinecodeatruntime,optimizingfrequentlyusedcode.2)TheJVMremainsplatform-independent,allowingthesameJavaapplicationtorunondifferen

为什么Java是开发跨平台桌面应用程序的流行选择?为什么Java是开发跨平台桌面应用程序的流行选择?Apr 25, 2025 am 12:23 AM

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runanywhere”哲学。1)itusesbytbytybytecebytecodethatrunsonanyjvm-platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

讨论可能需要在Java中编写平台特定代码的情况。讨论可能需要在Java中编写平台特定代码的情况。Apr 25, 2025 am 12:22 AM

在Java中编写平台特定代码的原因包括访问特定操作系统功能、与特定硬件交互和优化性能。1)使用JNA或JNI访问Windows注册表;2)通过JNI与Linux特定硬件驱动程序交互;3)通过JNI使用Metal优化macOS上的游戏性能。尽管如此,编写平台特定代码会影响代码的可移植性、增加复杂性、可能带来性能开销和安全风险。

与平台独立性相关的Java开发的未来趋势是什么?与平台独立性相关的Java开发的未来趋势是什么?Apr 25, 2025 am 12:12 AM

Java将通过云原生应用、多平台部署和跨语言互操作进一步提升平台独立性。1)云原生应用将使用GraalVM和Quarkus提升启动速度。2)Java将扩展到嵌入式设备、移动设备和量子计算机。3)通过GraalVM,Java将与Python、JavaScript等语言无缝集成,增强跨语言互操作性。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具