Andrid 多线程下载
本文转自:http://www.2cto.com/kf/201205/130969.html
本文将介绍在android平台下如何实现多线程下载,大家都知道,android平台使用java做为开发语言,所以java中支持的多线程下载方式在android平台下都支持,其中主要有两种方式可以实现多线程下载。
一种方式是使用很多个线程分别下载文件的不同部分,最后把所有下载完的文件合并成一个文件。另一种方式是使用java为我们提供的RandomAccessFile类实现多线程的下载。
从性能上分析,第二种方式的存取速度会慢一些,但开发起来较为容易,不需要进行合并文件等操作。本文将使用第二种方式来实现多线程下载,最终效果如下图所示:
第一步,我们先写一个线程类,来完成对指定区域的数据进行下载,如下所示:
Java代码
1. package com.ideasandroid.demo;
2.
3. import java.io.BufferedInputStream;
4. import java.io.File;
5. import java.io.IOException;
6. import java.io.RandomAccessFile;
7. import java.net.URL;
8. import java.net.URLConnection;
9.
10. import android.util.Log;
11. /**
12. * Copyright (C) 2010 ideasandroid
13. * 演示android多线程下载
14. * 欢迎访问http://www.2cto.com
15. * 让程序开发不再那么神秘
16. *
17. * 单个下载线程
18. */
19. public class FileDownloadThread extends Thread{
20. private static final int BUFFER_SIZE=1024;
21. private URL url;
22. private File file;
23. private int startPosition;
24. private int endPosition;
25. private int curPosition;
26. //用于标识当前线程是否下载完成
27. private boolean finished=false;
28. private int downloadSize=0;
29. public FileDownloadThread(URL url,File file,int startPosition,int endPosition){
30. this.url=url;
31. this.file=file;
32. this.startPosition=startPosition;
33. this.curPosition=startPosition;
34. this.endPosition=endPosition;
35. }
36. @Override
37. public void run() {
38. BufferedInputStream bis = null;
39. RandomAccessFile fos = null;
40. byte[] buf = new byte[BUFFER_SIZE];
41. URLConnection con = null;
42. try {
43. con = url.openConnection();
44. con.setAllowUserInteraction(true);
45. //设置当前线程下载的起点,终点
46. con.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
47. //使用java中的RandomAccessFile 对文件进行随机读写操作
48. fos = new RandomAccessFile(file, "rw");
49. //设置开始写文件的位置
50. fos.seek(startPosition);
51. bis = new BufferedInputStream(con.getInputStream());
52. //开始循环以流的形式读写文件
53. while (curPosition < endPosition) {
54. int len = bis.read(buf, 0, BUFFER_SIZE);
55. if (len == -1) {
56. break;
57. }
58. fos.write(buf, 0, len);
59. curPosition = curPosition + len;
60. if (curPosition > endPosition) {
61. downloadSize+=len - (curPosition - endPosition) + 1;
62. } else {
63. downloadSize+=len;
64. }
65. }
66. //下载完成设为true
67. this.finished = true;
68. bis.close();
69. fos.close();
70. } catch (IOException e) {
71. Log.d(getName() +" Error:", e.getMessage());
72. }
73. }
74.
75. public boolean isFinished(){
76. return finished;
77. }
78.
79. public int getDownloadSize() {
80. return downloadSize;
81. }
82. }
接下来就是使用图形界面来获取需要下载的内容,并实时更新下载进度条,代码如下所示:
Java代码
1. package com.ideasandroid.demo;
2.
3. import java.io.File;
4. import java.net.URL;
5. import java.net.URLConnection;
6. import android.app.Activity;
7. import android.os.Bundle;
8. import android.os.Environment;
9. import android.os.Handler;
10. import android.os.Message;
11. import android.view.View;
12. import android.view.View.OnClickListener;
13. import android.widget.Button;
14. import android.widget.EditText;
15. import android.widget.ProgressBar;
16. import android.widget.TextView;
17. /**
18. * Copyright (C) 2010 ideasandroid
19. * 演示android多线程下载
20. * 欢迎访问http://www.2cto.com
21. * 让程序开发不再那么神秘
22. */
23. public class FileDownloadDemo extends Activity {
24.
25. private EditText downloadUrl;
26. private EditText downloadFileName;
27. private EditText downloadThreadNum;
28. private Button downloadBt;
29. private ProgressBar downloadProgressBar;
30. private TextView progressMessage;
31. private int downloadedSize = 0;
32. private int fileSize = 0;
33.
34. @Override
35. public void onCreate(Bundle savedInstanceState) {
36. super.onCreate(savedInstanceState);
37. setContentView(R.layout.main);
38.
39. downloadUrl = (EditText) findViewById(R.id.downloadUrl);
40. downloadFileName = (EditText) findViewById(R.id.downloadFileName);
41. downloadThreadNum = (EditText) findViewById(R.id.downloadThreadNum);
42. progressMessage = (TextView) findViewById(R.id.progressMessage);
43. downloadBt = (Button) findViewById(R.id.downloadBt);
44. downloadProgressBar = (ProgressBar) findViewById(R.id.downloadProgressBar);
45. downloadProgressBar.setVisibility(View.VISIBLE);
46. downloadProgressBar.setMax(100);
47. downloadProgressBar.setProgress(0);
48. downloadBt.setOnClickListener(new OnClickListener() {
49. public void onClick(View v) {
50. download();
51. }
52. });
53. }
54.
55. private void download() {
56. // 获取SD卡目录
57. String dowloadDir = Environment.getExternalStorageDirectory()
58. + "/ideasdownload/";
59. File file = new File(dowloadDir);
60. //创建下载目录
61. if (!file.exists()) {
62. file.mkdirs();
63. }
64.
65. //读取下载线程数,如果为空,则单线程下载
66. int downloadTN = Integer.valueOf("".equals(downloadThreadNum.getText()
67. .toString()) ? "1" : downloadThreadNum.getText().toString());
68. //如果下载文件名为空则获取Url尾为文件名
69. int fileNameStart = downloadUrl.getText().toString().lastIndexOf("/");
70. String fileName = "".equals(downloadFileName.getText().toString()) ? downloadUrl
71. .getText().toString().substring(fileNameStart)
72. : downloadFileName.getText().toString();
73. //开始下载前把下载按钮设置为不可用
74. downloadBt.setClickable(false);
75. //进度条设为0
76. downloadProgressBar.setProgress(0);
77. //启动文件下载线程
78. new downloadTask(downloadUrl.getText().toString(), Integer
79. .valueOf(downloadTN), dowloadDir + fileName).start();
80. }
81.
82. Handler handler = new Handler() {
83. @Override
84. public void handleMessage(Message msg) {
85. //当收到更新视图消息时,计算已完成下载百分比,同时更新进度条信息
86. int progress = (Double.valueOf((downloadedSize * 1.0 / fileSize * 100))).intValue();
87. if (progress == 100) {
88. downloadBt.setClickable(true);
89. progressMessage.setText("下载完成!");
90. } else {
91. progressMessage.setText("当前进度:" + progress + "%");
92. }
93. downloadProgressBar.setProgress(progress);
94. }
95.
96. };
97.
98. /**
99. * @author ideasandroid
100. * 主下载线程
101. */
102. public class downloadTask extends Thread {
103. private int blockSize, downloadSizeMore;
104. private int threadNum = 5;
105. String urlStr, threadNo, fileName;
106.
107. public downloadTask(String urlStr, int threadNum, String fileName) {
108. this.urlStr = urlStr;
109. this.threadNum = threadNum;
110. this.fileName = fileName;
111. }
112.
113. @Override
114. public void run() {
115. FileDownloadThread[] fds = new FileDownloadThread[threadNum];
116. try {
117. URL url = new URL(urlStr);
118. URLConnection conn = url.openConnection();
119. //获取下载文件的总大小
120. fileSize = conn.getContentLength();
121. //计算每个线程要下载的数据量
122. blockSize = fileSize / threadNum;
123. // 解决整除后百分比计算误差
124. downloadSizeMore = (fileSize % threadNum);
125. File file = new File(fileName);
126. for (int i = 0; i < threadNum; i++) {
127. //启动线程,分别下载自己需要下载的部分
128. FileDownloadThread fdt = new FileDownloadThread(url, file,
129. i * blockSize, (i + 1) * blockSize - 1);
130. fdt.setName("Thread" + i);
131. fdt.start();
132. fds[i] = fdt;
133. }
134. boolean finished = false;
135. while (!finished) {
136. // 先把整除的余数搞定
137. downloadedSize = downloadSizeMore;
138. finished = true;
139. for (int i = 0; i < fds.length; i++) {
140. downloadedSize += fds[i].getDownloadSize();
141. if (!fds[i].isFinished()) {
142. finished = false;
143. }
144. }
145. //通知handler去更新视图组件
146. handler.sendEmptyMessage(0);
147. //休息1秒后再读取下载进度
148. sleep(1000);
149. }
150. } catch (Exception e) {
151.
152. }
153.
154. }
155. }
Andrid 多线程下载的更多相关文章
- 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】
一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...
- Java--使用多线程下载,断点续传技术原理(RandomAccessFile)
一.基础知识 1.什么是线程?什么是进程?它们之间的关系? 可以参考之前的一篇文章:java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器 简 ...
- android 多线程下载 断点续传
来源:网易云课堂Android极客班第八次作业练习 练习内容: 多线程 asyncTask handler 多线程下载的原理 首先获取到目标文件的大小,然后在磁盘上申请一块空间用于保存目标文件,接着把 ...
- Linux下多线程下载工具 - Axel
Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件.适合网速不给力时多线程下载提高下载速度.比如在国 ...
- linux多线程下载工具mwget
linux多线程下载工具mwget 经常使用wget进行文件下载,然而wget的处理速度并不如人意.遇到一些国外的站点,经常慢得像蜗牛一般.然而为了解决这个问题,便有了mwget:m表示multi多线 ...
- 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)
1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...
- Java 仿迅雷多线程下载
package net.webjoy.jackluo.android_json; /** * 1.http Range "bytes="+ start+end * 2.Random ...
- Python3 多线程下载代码
根据http://www.oschina.net/code/snippet_70229_2407修改而来的增强版.貌似原版源自Axel这个多线程下载工具. ''' Created on 2014-10 ...
- android程序---->android多线程下载(一)
多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...
随机推荐
- Mutex(测量)
游标共享怎样使用Mutex kks 使用mutex以便保护对于下述基于parent cursor父游标和子游标child cursor的一系列操作 对于父游标parent cursor的操作: 基于发 ...
- 50个最受网友欢迎的HTML5资源下载列表
完整附件下载地址:http://down.51cto.com/data/413867 附件预览: HTML 5游戏源码精选(共含9个游戏源码) http://down.51cto.com/zt/227 ...
- notepad扩展搜索,正则搜索
Dos和windows采用回车+换行CR/LF表示下一行, 0d 0a 两个字节表示而UNIX/Linux采用’\n’换行符LF表示下一行(ASCII代码是10),0a一个字节表示MAC OS系统则采 ...
- Python重写C语言程序100例--Part6
''' [程序41] 题目:学习static定义静态变量的使用方法 1.程序分析: 2.程序源码: ''' # python没有这个功能了,仅仅能这样了:) def varfunc(): var = ...
- 设计模式六大原则(4):接口隔离原则(Interface Segregation Principle)
接口隔离原则: 使用多个专门的接口比使用单一的总接口要好. 一个类对另外一个类的依赖性应当是建立在最小的接口上的. 一个接口代表一个角色,不应当将不同的角色都交给一个接口.没有关系的接口合并在一起,形 ...
- SCSI miniport 驾驶一个简单的框架
前段时间,只需用一台新电脑,由于资金有限没有匹配了心仪已久的SSD.我没感觉到飞翔的感觉,总不甘心,仔细想想.我死了相当大的存储,我们可以假设部分内存作为硬盘驱动器把它弄出来.不会比固态硬盘的速度快, ...
- c++ 按行读取txt文本
CStdioFile 类的声明保存在 afx.h 头文件中. CStdioFile 类继承自 CFile 类, CStdioFile 对象表示一个用运行时的函数 fopen 打开的 c 运行时的流式文 ...
- MYSQL中取当前年份的第一天和当前周,月,季度的第一天/最后一天
mysql 获取当年第一天的年月日格式:SELECT DATE_SUB(CURDATE(),INTERVAL dayofyear(now())-1 DAY); MySQL里获取当前week.month ...
- 聊聊高并发(二十九)解析java.util.concurrent各个组件(十一) 再看看ReentrantReadWriteLock可重入读-写锁
上一篇聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁 讲了可重入读写锁的基本情况和基本的方法,显示了怎样 ...
- Android-Universal-Image-Loader学习笔记(一个)
Android-Universal-Image-Loader它是一个开源项目,处理图像加载和缓存.闲暇的时候,读一些源.特别记录. 所述图像文件(磁盘)高速缓存,我们需要考虑的因素,如以下 1) 定 ...