本文转自: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.     }

转载于:https://www.cnblogs.com/tianyaxue/p/3166115.html

Andrid 多线程下载相关推荐

  1. libcurl使用多线程下载大文件源码示例!

    使用libcurl多线程下载大文件的基本思想: 首选打开文件,将文件等分为指定的片段,使用http range下载,一个线程下载一个片段,当线程下载片段时,它们将数据写到打开文件的指定位置,类似BT文 ...

  2. [Mac] mac linux 多线程下载利器 axel

    ​> 之前做过一些文件下载的统计,发现谷歌浏览器chrome和火狐firefox, 一般都是单线程的下载文件,360浏览器却是多线程的下载. 如今切换到了mac上,发现没有360哪个浏览器,就像 ...

  3. 基于流式的md5计算-多线程下载工具Lwget介绍

    在数据传输的时候,我们希望实现以下目标: 1. 使用多线程传输,加速下载速度 2. 数据在传输过程中,进行流式md5计算,避免在传输完毕之后校验大文件 3. 支持断点续传 4. 支持http协议和ft ...

  4. 断点续传---多线程下载进阶(一)

    打算总结7篇笔记.来学习下断点续传---多线程下载进阶 AndroidManifest.xml <?xml version="1.0" encoding="utf- ...

  5. Android -- 多线程下载

    因为Android应用程序是java写的,基本上很多java写的程序都可以直接照搬到Android上面,移植性非常Good.这里讲一下多线程下载,就是每个线程都下载自己的那部分,那么就需要平均分配分割 ...

  6. Android 多线程下载 显示进度 速度

    功能要求:从网络下载一APK应用,显示下载速度.进度,并安装应用. 运行效果图: 工程结构图: 很简单,就一个activity,一个更新UI的线程,一个下载线程加个文件处理类 主要代码: /***多线 ...

  7. 多线程下载问题(IDHTTP)

    小弟写了一个多线程下载的程序,总是有死循环的迹象,不过我认为可能是产生了死锁.可是当单步跟踪的时候产生错误大家帮小弟看看啊:             unit   IndyMThread;       ...

  8. android 多线程下载,断点续传,线程池

    android 多线程下载,断点续传,线程池 你可以在这里看到这个demo的源码: https://github.com/onlynight/MultiThreadDownloader 效果图 这张效 ...

  9. python代码示例下载-Python实现多线程下载脚本的示例代码

    0x01 分析 一个简单的多线程下载资源的Python脚本,主要实现部分包含两个类: Download类:包含download()和get_complete_rate()两种方法.download() ...

最新文章

  1. opencvmediapipe 人脸检测+摄像头实时
  2. BugKuCTF 杂项 签到题
  3. 用作键提取器的函数的 Boost.MultiIndex 示例
  4. Basic链表与队列的区别
  5. C# 搭建自己的NuGet服务器,上传自定义NuGet包
  6. 采访田飞师兄有感 ——by 李皈颖
  7. 手把手教你写网站:Python WEB开发技术实战
  8. 游戏美术设计干货分享:制造“冲突”,提高画面张力
  9. 收藏 | 关于Mac Dock的10 个隐藏终端命令
  10. leetcode problem 41 -- First Missing Positive
  11. shoppping collection
  12. 计算机桌面移动如何解决,【电脑小知识】桌面布局被锁定,图标不能随意移动了怎么办?...
  13. html唱片机效果,黑胶唱片风格音频播放器jQuery插件
  14. tair用ldb做分布式存储
  15. Web Api 调用时出现405错误解决方案
  16. 【linux】循序渐进学运维-基础篇-linux运维级别
  17. mysql 实现日期格式化(date_format)
  18. android adb点击坐标,Android adb shell 获得点击屏幕的位置坐标
  19. php 查询数据表第2条,PHP 连接 MySQL 数据库的连接函数 mysql_connect 的第二个参数是( )。...
  20. 这些大厂笔试题 你都见识(被无情鞭挞)过了吗?—— 哔哩哔哩篇

热门文章

  1. CAD制图的时候,怎样绘制CAD螺旋图形?
  2. ict测试机台_ICTFCT自动测试机 PTI-2000L 深圳市派捷电子科技有限公司
  3. 【Java从零到架构师第③季】【26】SpringMVC-反射获取方法参数名_SpringMVC是如何获取方法的参数名的
  4. 定位生产问题时,异常堆栈莫名丢了,何解?
  5. Fiddler抓包工具使用(一)
  6. 西瓜书决策树实现(基于ID3)补充——采用自定义数据结构实现
  7. 一秒连接快速密封的管道密封连接器
  8. 什么是 block
  9. cors数据类型_如何根据RTK的差分格式选择千寻cors账号的源节点进行设置?
  10. 视频教程-ReactNative初级到项目实战-ReactNative