本篇文章主要介绍了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多线程如何下载文件的实例的详细内容。