Android 系列笔记 五

多线程下载

原理:
服务器CPU分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public void multiThreadDownload(String path){
int threadCount = 3;
URL url = new URL(path);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(10000);//设置请求超时时间
conn.setReadTimeout(5000);//设置读取超时时间
conn.setRequestMethod("GET");//设置请求类型
conn.connect();

int responseCode = conn.getResponseCode();//获取请求响应码
if (responseCode == 200) {//请求成功
int length = conn.getContentLength();
int singleFileSize = length / threadCount;
//生成一个跟要下载文件大小相同的临时文件
File tempFile = new File("abc.rmvb");
RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rwd");
//创建与服务器上资源同等大小的空文件
tempRaf.setLength(length);
tempRaf.close();
for(int i = 0; i < threadCount; i++){
int start = i * singleFileSize;
int end = (i + 1) * singleFileSize - 1;
if(i == threadCount - 1)
end = length - 1;
new Thread(){
@Override
public void run(){
URL url = new URL(path);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(10000);//设置请求超时时间
conn.setReadTimeout(5000);//设置读取超时时间
conn.setRequestMethod("GET");//设置请求类型
//设置文件读取起始位置及结束位置
conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
conn.connect();
if (responseCode == 206) {//请求部分数据,响应码为206
InputStream is = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
//拿到临时文件输出流的引用
File file = new File("abc.rmvb.part");
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//将文件写入位置移动至start
raf.seek(start);
while((len = is.read(buffer)) != -1){
raf.write(buffer, 0 ,len);
}
raf.close();
}
}
}.start();
}
}
}

断点续传

用单独文件记录下载位置

1
2
3
4
5
6
7
8
9
int total;//当前已经下载大小
File progressFile = new File(threadId + ".txt");
RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
//每次读取数据后,同步把当前下载的总进度接入到进度临时文件中
progressRaf.write((total + "").getBytes());
progressRaf.close();
//继续下载的时候 先判断记录文件是否存在
//若存在的话,读取已经下载的大小total,再继续下载
start += total;

ProgressBar 进度条

1
2
3
4
5
//可以在子线程中刷新UI
//设置进度条的最大值
pb.setMax(length);
//设置当前进度
pb.setProgress(total);

第三方框架 xUtils

支持多线程、断点续传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void download(String path){
HttpUtils utils = new HttpUtils();
HttpHandler handler = utils.download(path,
"", //保存路径
true, //是否支持断点续传,如果服务器不支持range属性,则重新下载
true, //如果从请求返回信息中获取到文件名,下载完成后自动重命名
new RequestCallBack<File>(){
@Override
public void onStart(){

}
//下载成功后调用
@Override
public void onSuccess(ResponseInfo<File> responseInfo){

}
@Override
public void onFailure(HttpException error, String msg){

}
@Override
public void onLoading(long total, long current, boolean isUploading){

}
});
}