zoukankan      html  css  js  c++  java
  • 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.     } 

  • 相关阅读:
    操作系统复习
    软件工程复习
    2020字节跳动校园招聘算法方向第二场考试题解(部分)
    【牛客】用两个栈来实现一个队列
    LeetCode 62. 不同路径
    LeetCode 79. 单词搜索
    LeetCode 113. 路径总和 II
    LeetCode 389. 找不同
    【牛客】矩阵交换
    【牛客】KiKi学习了结构体和指针
  • 原文地址:https://www.cnblogs.com/tianyaxue/p/3166115.html
Copyright © 2011-2022 走看看