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);
  }

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

(0)

相关推荐

  • Java通过卖票理解多线程

    以卖票的例子来介绍多线程和资源共享,下面我们来看看为什么要用卖票作为例子. 卖票是包含一系列动作的过程,有各种操作,例如查询票.收钱.数钱.出票等,其中有一个操作是每次卖掉一张,就将总的票数减去1.有10张票,如果一个人卖票,先做查票.收钱.数钱等各种操作,再将总的票数减去1,效率很低.如果多个人卖票,每个人都是做同样的操作,数钱.检查钱,最后将总的票数减1,这样效率高.但是有一个问题,如果出现两个人同时将总的票数减掉了1,例如,A.B两个人同时读取到票的总数是10,A从中减去1,同时B也从中减

  • java 多线程的同步几种方法

    java 多线程的同步几种方法 一.引言 前几天面试,被大师虐残了,好多基础知识必须得重新拿起来啊.闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常.举个例子,如果一个银行账户同时被两个线程操作,一个取100块,一个存钱100块.假设账户原本有0块,如果取钱线程和存钱线程同时发生,会出现什么结果呢?取钱不成功,账户余额是100.取钱成功了,账户余额是0.那到底是哪个

  • Java利用future及时获取多线程运行结果

    Future接口是Java标准API的一部分,在java.util.concurrent包中.Future接口是Java线程Future模式的实现,可以来进行异步计算. 有了Future就可以进行三段式的编程了,1.启动多线程任务2.处理其他事3.收集多线程任务结果.从而实现了非阻塞的任务调用.在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否有结果,或者使用get()函数来阻塞式获取执行结果.这样就不能实时跟踪其他线程的结果状态了,所以直接使用g

  • Java基于Socket实现简单的多线程回显服务器功能示例

    本文实例讲述了Java基于Socket实现简单的多线程回显服务器功能.分享给大家供大家参考,具体如下: 需要两个类,一个是EchoServer,代表服务器.另外一个是EchoServerClient,代表客户端.代码如下: package interview; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter

  • Java多线程ForkJoinPool实例详解

    引言 java 7提供了另外一个很有用的线程池框架,Fork/Join框架 理论 Fork/Join框架主要有以下两个类组成. * ForkJoinPool 这个类实现了ExecutorService接口和工作窃取算法(Work-Stealing Algorithm).它管理工作者线程,并提供任务的状态信息,以及任务的执行信息 * ForkJoinTask 这个类是一个将在ForkJoinPool执行的任务的基类. Fork/Join框架提供了在一个任务里执行fork()和join()操作的机制

  • 详解Java中多线程异常捕获Runnable的实现

    详解Java中多线程异常捕获Runnable的实现 1.背景: Java 多线程异常不向主线程抛,自己处理,外部捕获不了异常.所以要实现主线程对子线程异常的捕获. 2.工具: 实现Runnable接口的LayerInitTask类,ThreadException类,线程安全的Vector 3.思路: 向LayerInitTask中传入Vector,记录异常情况,外部遍历,判断,抛出异常. 4.代码: package step5.exception; import java.util.Vector

  • 浅谈Java多线程处理中Future的妙用(附源码)

    java 中Future是一个未来对象,里面保存这线程处理结果,它像一个提货凭证,拿着它你可以随时去提取结果.在两种情况下,离开Future几乎很难办.一种情况是拆分订单,比如你的应用收到一个批量订单,此时如果要求最快的处理订单,那么需要并发处理,并发的结果如果收集,这个问题如果自己去编程将非常繁琐,此时可以使用CompletionService解决这个问题.CompletionService将Future收集到一个队列里,可以按结果处理完成的先后顺序进队.另外一种情况是,如果你需要并发去查询一

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

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

  • Python实现多线程下载脚本的示例代码

    0x01 分析 一个简单的多线程下载资源的Python脚本,主要实现部分包含两个类: Download类:包含download()和get_complete_rate()两种方法. download()方法种首先用 urlopen() 方法打开远程资源并通过 Content-Length获取资源的大小,然后计算每个线程应该下载网络资源的大小及对应部分吗,最后依次创建并启动多个线程来下载网络资源的指定部分. get_complete_rate()则是用来返回已下载的部分占全部资源大小的比例,用来回

  • Java使用sftp定时下载文件的示例代码

    sftp简介 sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的网络的加密方法.sftp 与 ftp 有着几乎一样的语法和功能.SFTP 为 SSH的其中一部分,是一种传输档案至 Blogger 伺服器的安全方式.其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)

  • Nginx配置实现下载文件的示例代码

    偶尔听人说用nginx实现文件上传下载,之前看nginx实践大致看到过,没有细究.所以今天就想研究下nginx实现文件的上传下载,直接开搞,本地服务启起.这里记录下配置及踩坑记录. 一.配置 http { ... server: { # 配置下载 location /download { root D:\\download; autoindex on; autoindex_exact_size off; } } ... } 这是目录里随便放的几个文件,可以看到实现成功. 这里踩过几个坑,下面提示

  • Java多线程下载文件实例详解

    本文实例为大家分享了Java多线程下载文件的具体代码,供大家参考,具体内容如下 import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MulThreadDownload { public static void main(String[] args)

  • Android实现多线程下载文件的方法

    本文实例讲述了Android实现多线程下载文件的方法.分享给大家供大家参考.具体如下: 多线程下载大概思路就是通过Range 属性实现文件分段,然后用RandomAccessFile 来读写文件,最终合并为一个文件 首先看下效果图: 创建工程 ThreadDemo 首先布局文件 threaddemo.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo

  • C# 文件上传下载(Excel导入,多线程下载)功能的实现代码

    废话不多说了,直接给大家贴代码,具体代码如下所示: //打开Excel文件,转换为DataTable DataTable dtExcel; private void OpenFile() { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Microsoft Excel files(*.xls)|*.xls;*.xlsx"; //筛选打开文件类型 :图片 *.jpg|*.jpg|*.bmp|*.bmp ;&q

  • android实现多线程下载文件(支持暂停、取消、断点续传)

    多线程下载文件(支持暂停.取消.断点续传) 多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可. 涉及的知识及问题 请求的数据如何分段 分段完成后如何下载和下载完成后如何组装到一起 暂停下载和继续下载的实现(wait().notifyAll().synchronized的使用) 取消下载和断点续传的实现 一.请求的数据如何分段 首先通过HttpURLConne

  • Python多线程下载文件的方法

    本文实例讲述了Python多线程下载文件的方法.分享给大家供大家参考.具体实现方法如下: import httplib import urllib2 import time from threading import Thread from Queue import Queue from time import sleep proxy = 'your proxy'; opener = urllib2.build_opener( urllib2.ProxyHandler({'http':proxy

  • C#实现多线程下载文件的方法

    本文实例讲述了C#实现多线程下载文件的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Threading; using System.Net; namespace WfpApp { public class MultiDownload { #region 变量 pri

随机推荐