Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之單線程下載與多線程下載

Android之單線程下載與多線程下載

編輯:關於Android編程

概述:

單線程下載很簡單,就是開啟一個線程去下載資源再進行本地保存;

多線程下載是通過RandomAccessFile(隨機文件讀寫操作類)來設置每個線程讀取文件的起始點位置,起始點之間的長度即為該線程需要下載的文件大小

下載開始位置:線程id*每條線程下載的數據長度 = ?

下載結束位置:(線程id+1)*每條線程下載的數據長度-1=?
這裡用的是URLConnection

單線程下載與多線程下載

public class DownloadActivity extends Activity implements View.OnClickListener {

    private Button mButtonSingle;
    private Button mButtonMuti;

    private SeekBar mSeekBarDownload;
    private int fileLength;
    //handler用於接收多線程下載線程的消息Message,並得到文件下載進度寫入進度條SeekBar
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0x23:
                    mSeekBarDownload.setProgress(msg.arg1*100/fileLength);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_download);

        mSeekBarDownload = (SeekBar) findViewById(R.id.seekBar_download);
        mButtonSingle = (Button) findViewById(R.id.button_download_single);
        mButtonMuti = (Button) findViewById(R.id.button_download_muti);

        mButtonSingle.setOnClickListener(this);
        mButtonMuti.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button_download_single:
                new SingleDownloadTask().execute();
                break;
            case R.id.button_download_muti:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        downloadMuti();
                    }
                }).start();
                break;
            default:
                break;
        }
    }

    /**
     * 多線程下載方式
     * 作用是打開網絡連接,建立被下載文件存放路徑,開啟多個下載線程並發送文件下載進度的消息
     */
    private void downloadMuti() {
        try {
            String urlPath = http://192.168.0.30:8080/MyWebTest/music/aa.mp3;
            URL url = new URL(urlPath);
            //連接下載地址
            URLConnection connection = url.openConnection();
            //得到文件長度
            fileLength = connection.getContentLength();
            //找到或創建下載文件的存放路徑
            File file = new File(Environment.getExternalStorageDirectory(),ee.mp3);
            if(!file.exists()){
                file.createNewFile();
            }
            MutiThread[] threads = new MutiThread[5];
            //進行五次分段下載,因為int型的整除會捨棄余數,最後一個進程下載的長度是從文件長度的4/5到文件總長度
            for(int i=0;i<5;i++){
                MutiThread thread = null;
                if(i==4){
                    thread = new MutiThread(fileLength/5*4,fileLength,urlPath,file.getAbsolutePath());
                }else{
                    thread = new MutiThread(fileLength/5*i,fileLength/5*(i+1)-1,urlPath,file.getAbsolutePath());
                }
                thread.start();
                threads[i] = thread;
            }
            boolean isFinish = true;
            //如果沒有下載完全時不斷的更新下載進度,數據通過Message傳遞給handler
            while (isFinish){
                int sum=0;
                for(MutiThread thread:threads){
                    sum+=thread.getSum();
                }
                Message msg = handler.obtainMessage();
                msg.what = 0x23;
                msg.arg1 = sum;
                handler.sendMessage(msg);
                //一般一個被下載的文件可能無法下載完全
                if(sum+10>fileLength){
                    isFinish=false;
                }
                //被隔一秒,更新一次進度
                Thread.sleep(1000);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //單線程下載,用的是AsyncTask線程
    class SingleDownloadTask extends AsyncTask{
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            mSeekBarDownload.setProgress((int) (values[0]*100.0/values[1]));
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
        }

        @Override
        protected String doInBackground(String... params) {
            try {
                URL url = new URL(http://192.168.0.30:8080/MyWebTest/music/aa.mp3);
                URLConnection connection = url.openConnection();
                int length = connection.getContentLength();
                InputStream is = connection.getInputStream();
                File file = new File(Environment.getExternalStorageDirectory(),aa.mp3);
                if(!file.exists()){
                    file.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(file);
                byte[] array = new byte[1024];
                int index = is.read(array);
                int progress = 0;
                while(index!=-1){
                    fos.write(array,0,index);
                    progress+=index;
                    publishProgress(progress,length);
                    index = is.read(array);
                }
                fos.flush();
                fos.close();
                is.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

多線程的下載線程的寫法

public class MutiThread extends Thread {
    private int sum = 0;
    private long start;
    private long end;
    private String urlPath;
    private String filePath;

    public MutiThread(long start, long end, String urlPath, String filePath) {
        this.start = start;
        this.end = end;
        this.urlPath = urlPath;
        this.filePath = filePath;
    }

    public int getSum() {
        return sum;
    }

    @Override
    public void run() {
        try {
            URL url  = new URL(urlPath);
            URLConnection connection = url.openConnection();
            connection.setAllowUserInteraction(true);
            //設置當前線程下載的起點,終點
            connection.setRequestProperty(Range, bytes= + start + - + end);
            InputStream is = connection.getInputStream();
            byte[] array = new byte[1024];
            File file = new File(filePath);
            //使用java中的RandomAccessFile 對文件進行隨機讀寫操作
            RandomAccessFile randomAccessFile = new RandomAccessFile(file,rw);
            //設置開始寫文件的位置
            randomAccessFile.seek(start);
            int index = is.read(array);
            //開始循環以流的形式讀寫文件
            while(index!=-1){
                randomAccessFile.write(array,0,index);
                sum += index;
                index = is.read(array);
            }
            randomAccessFile.close();
            is.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

結果演示:
單線程下載:
這裡寫圖片描述

多線程下載:
這裡寫圖片描述

顯然,多線程下載要比單線程下載快得多,但前提是手機是多核的。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved