RxJava2.x+ReTrofit2.x多线程下载文件的示例代码
程序员文章站
2024-03-01 12:50:22
写在前面:
接到公司需求:要做一个apk升级的功能,原理其实很简单,百度也一大堆例子,可大部分都是用框架,要么就是httpurlconnection,实在是不想这么干。正...
写在前面:
接到公司需求:要做一个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); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。