android中级篇之多线程下载

要是先多线程下载,则必须对同一个文件可任意位置的写入 ,java中提供这样一个类可任意写入RandomAccessFile 。通过多线程,可将文件分割成多个子断,每一个线程只需下载一段文件即可。实现效果如图:


 

下面看代码部分:

1.布局文件 main.xml

 

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <TextView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="wrap_content"   
  10.     android:text="下载路径"  
  11.     />  
  12. <EditText  
  13.     android:id="@+id/mEditText"  
  14.     android:layout_width="fill_parent"  
  15.     android:layout_height="wrap_content"  
  16.     android:singleLine="true"  
  17.     android:text="http://android.yesky.com/uploads/attachments/2010-04/27/a5964152.jpg"/>     
  18. <ProgressBar  
  19.     android:id="@+id/mBar"  
  20.     android:layout_width="fill_parent"  
  21.     android:layout_height="wrap_content"  
  22.     android:visibility="invisible"  
  23.     style="?android:attr/progressBarStyleHorizontal"/>     
  24. <Button  
  25.     android:id="@+id/mButton"  
  26.     android:layout_width="fill_parent"    
  27.     android:layout_height="wrap_content"  
  28.     android:text="下载"/>  
  29. </LinearLayout>  

 

 

2.下载工具类 Download.java

 

  1. package com.yin.downloader.utils;  
  2. import java.io.File;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.RandomAccessFile;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.MalformedURLException;  
  8. import java.net.URL;  
  9. import android.content.Context;  
  10. import android.util.Log;  
  11. public class Download {  
  12.     private String SDPath = null;  
  13.     private static final String TAG = "com.yin.download";  
  14.     private RandomAccessFile randomFile = null;  
  15.     private URL  url;  
  16.     private Context context;  
  17.     private String urlStr;  
  18.     private String fileName;  
  19.     private int fileSize;  
  20.     private int totalReadSize;  
  21.     public Download(String urlStr,String fileName,String SDPath,Context context){  
  22.         this.context = context;  
  23.         this.fileName = fileName;  
  24.         this.urlStr = urlStr;  
  25.         this.SDPath = SDPath;  
  26.     }  
  27.       
  28.     public void downloadFile(){  
  29.         try {  
  30.             File file = new File(SDPath+fileName);  
  31.             url = new URL(urlStr);  
  32.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  33.             conn.setRequestMethod("GET");  
  34.             //获得下载文件的大小  
  35.             fileSize = conn.getContentLength();  
  36.             //设置线程的大小,考虑手机的性能,并不是越大越好  
  37.             int threadSize = 3;  
  38.             //每个线程下载文件+的部分大小        +1 避免文件下载不完全  
  39.             int block = fileSize / threadSize +1;  
  40.             for(int i=0;i<3;i++){  
  41.                 int startPosition = i * block;  
  42.                 //创建可任意位置读取的文件  
  43.                 randomFile = new RandomAccessFile(file, "rw");  
  44.                 randomFile.seek(startPosition);  
  45.                 new DownloadThread(i+1, startPosition, block, randomFile).start();  
  46.             }  
  47.           
  48.         } catch (MalformedURLException e) {  
  49.             Log.e(TAG, "MalformedURLException");  
  50.             e.printStackTrace();  
  51.         } catch (IOException e) {  
  52.             Log.e(TAG, "IOException");  
  53.             e.printStackTrace();  
  54.         }  
  55.     }  
  56.       
  57.     //下载文件的线程  
  58.     private class DownloadThread extends Thread{  
  59.           
  60.         private int threadID;  
  61.         private int startPosition;  
  62.         private int block;  
  63.         private RandomAccessFile randomFile;  
  64.         public DownloadThread(int threadID, int startPosition, int block,  
  65.                 RandomAccessFile randomFile) {  
  66.             super();  
  67.             this.threadID = threadID;  
  68.             this.startPosition = startPosition;  
  69.             this.block = block;  
  70.             this.randomFile = randomFile;  
  71.         }  
  72.           
  73.         public void run() {  
  74.             try {  
  75.                 HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  76.                 conn.setRequestMethod("GET");  
  77.                 //文件下载位置   规定的格式 “byte=xxxx-”  
  78.                 String start = "bytes="+startPosition + "-";  
  79.                 //设置文件开始的下载位置  
  80.                 conn.setRequestProperty("Range", start);  
  81.                 InputStream is = conn.getInputStream();  
  82.                 byte[] buffer = new byte[4*1024];  
  83.                 int len = -1;  
  84.                 int readFileSize = 0;  
  85.                 while((readFileSize < block) && ((len = is.read(buffer)) != -1)){  
  86.                     randomFile.write(buffer,0,len);  
  87.                     readFileSize += len ;  
  88.                     totalReadSize += readFileSize;  
  89.                 }  
  90.                 System.out.println("线程 :"+threadID+" 下载完成");      
  91.                 is.close();  
  92.                 randomFile.close();  
  93.                 conn.disconnect();  
  94.                   
  95.             } catch (IOException e) {  
  96.                 Log.e(TAG+":child""IOException");  
  97.                 e.printStackTrace();  
  98.             }  
  99.         }  
  100.     }  
  101.     public int getFileSize() {  
  102.         return fileSize;  
  103.     }  
  104.     public void setFileSize(int fileSize) {  
  105.         this.fileSize = fileSize;  
  106.     }  
  107.     public int getTotalReadSize() {  
  108.         return totalReadSize;  
  109.     }  
  110.     public void setTotalReadSize(int totalReadSize) {  
  111.         this.totalReadSize = totalReadSize;  
  112.     }  
  113. }  

 

3.DownloadActivity.java

 

  1. package com.yin.downloader;  
  2. import java.util.Timer;  
  3. import java.util.TimerTask;  
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6. import android.os.Environment;  
  7. import android.os.Handler;  
  8. import android.os.Message;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. import android.widget.EditText;  
  13. import android.widget.ProgressBar;  
  14. import android.widget.Toast;  
  15. import com.yin.downloader.utils.Download;  
  16. public class DownloadActivity extends Activity {  
  17.     public EditText mEditText;  
  18.     public ProgressBar mBar;  
  19.     public Button mButton;  
  20.     public String urlStr;  
  21.     public String fileName;  
  22.     public String SDPath = "/sdcard/";  
  23.     public int fileSize;  
  24.     public int totalReadSize;  
  25.     Download download;  
  26.       
  27.     public Handler handler = new Handler(){  
  28.         @Override  
  29.         public void handleMessage(Message msg) {  
  30.               
  31.             mBar.setProgress(download.getTotalReadSize());  
  32.             mBar.invalidate();  
  33.         }  
  34.           
  35.     };  
  36.       
  37.     public Timer mTimer = new Timer();  
  38.     public TimerTask mTask = new TimerTask() {  
  39.           
  40.         @Override  
  41.         public void run() {  
  42.             Message msg = new Message();  
  43.             handler.sendMessage(msg);  
  44.         }  
  45.     };  
  46.       
  47.     public void onCreate(Bundle savedInstanceState) {  
  48.         super.onCreate(savedInstanceState);  
  49.         setContentView(R.layout.main);  
  50.         mEditText = (EditText) findViewById(R.id.mEditText);  
  51.         mBar = (ProgressBar) findViewById(R.id.mBar);  
  52.         mButton = (Button) findViewById(R.id.mButton);  
  53.         mButton.setOnClickListener(new ClickEven());  
  54.           
  55.         fileName = "my.jpg";  
  56.         //判断SDcard是否存在。  
  57.         if(Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED){  
  58.             SDPath ="/sdcard/";  
  59.         }else{  
  60.             Toast.makeText(this"SDcard不存在", Toast.LENGTH_LONG).show();  
  61.         }  
  62.         
  63.     }  
  64.       
  65.     private class ClickEven implements OnClickListener{  
  66.           
  67.         public void onClick(View v) {  
  68.             urlStr = mEditText.getText().toString();  
  69.             mBar.setVisibility(View.VISIBLE);  
  70.             download = new Download(urlStr,fileName,SDPath,DownloadActivity.this);  
  71.             download.downloadFile();  
  72.             //将progressbar的大小设置为下载文件大小  
  73.             mBar.setMax(download.getFileSize());  
  74.             //定时刷新  
  75.             mTimer.schedule(mTask, 0200);  
  76.         }  
  77.           
  78.     }  
  79. }  

此例实现比较简单,还可以加入断点续传的功能,把程序停止时当前线程现在的位置存入数据库中,再次下载时从数据库中取出即可;

原文地址:https://www.cnblogs.com/zhwl/p/2548004.html