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

[Android-011][多線程下載]

編輯:關於Android編程

 

 多線程下載

原理:服務器CPU分配給每條線程的時間片相同,服務器帶寬平均分配給每條線程,所以客戶端開啟的線程越多,就能搶占到更多的服務器資源

確定每條線程下載多少數據

發送http請求至下載地址
        String path = http://192.168.1.102:8080/editplus.exe;     
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(5000);
        conn.setConnectTimeout(5000);
        conn.setRequestMethod(GET);       
獲取文件總長度,然後創建長度一致的臨時文件
        if(conn.getResponseCode() == 200){
            //獲得服務器流中數據的長度
            int length = conn.getContentLength();
            //創建一個臨時文件存儲下載的數據
            RandomAccessFile raf = new RandomAccessFile(getFileName(path), rwd);
            //設置臨時文件的大小
            raf.setLength(length);
            raf.close();
確定線程下載多少數據
            //計算每個線程下載多少數據
            int blockSize = length / THREAD_COUNT;

計算每條線程下載數據的開始位置和結束位置

        for(int id = 1; id <= 3; id++){
            //計算每個線程下載數據的開始位置和結束位置
            int startIndex = (id - 1) * blockSize;
            int endIndex = id * blockSize - 1;
            if(id == THREAD_COUNT){
                endIndex = length;
            }

            //開啟線程,按照計算出來的開始結束位置開始下載數據
            new DownLoadThread(startIndex, endIndex, id).start();
        }

再次發送請求至下載地址,請求開始位置至結束位置的數據

        String path = http://192.168.1.102:8080/editplus.exe;

        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(5000);
        conn.setConnectTimeout(5000);
        conn.setRequestMethod(GET);

        //向服務器請求部分數據
        conn.setRequestProperty(Range, bytes= + startIndex + - + endIndex);
        conn.connect();
* 下載請求到的數據,存放至臨時文件中

        if(conn.getResponseCode() == 206){
            InputStream is = conn.getInputStream();
            RandomAccessFile raf = new RandomAccessFile(getFileName(path), rwd);
            //指定從哪個位置開始存放數據
            raf.seek(startIndex);
            byte[] b = new byte[1024];
            int len;
            while((len = is.read(b)) != -1){
                raf.write(b, 0, len);
            }
            raf.close();
        }

帶斷點續傳的多線程下載

定義一個int變量記錄每條線程下載的數據總長度,然後加上該線程的下載開始位置,得到的結果就是下次下載時,該線程的開始位置,把得到的結果存入緩存文件
        //用來記錄當前線程總的下載長度
        int total = 0;
        while((len = is.read(b)) != -1){
            raf.write(b, 0, len);
            total += len;
            //每次下載都把新的下載位置寫入緩存文本文件
            RandomAccessFile raf2 = new RandomAccessFile(threadId + .txt, rwd);
            raf2.write((startIndex + total + ).getBytes());
            raf2.close();
        }
下次下載開始時,先讀取緩存文件中的值,得到的值就是該線程新的開始位置
        FileInputStream fis = new FileInputStream(file);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        String text = br.readLine();
        int newStartIndex = Integer.parseInt(text);
        //把讀到的值作為新的開始位置
        startIndex = newStartIndex;
        fis.close();
三條線程都下載完畢之後,刪除緩存文件
        RUNNING_THREAD--;
        if(RUNNING_THREAD == 0){
            for(int i = 0; i <= 3; i++){
                File f = new File(i + .txt);
                f.delete();
            }
        }

手機版的斷點續傳多線程下載器

把剛才的代碼直接粘貼過來就能用,記得在訪問文件時的路徑要改成Android的目錄,添加訪問網絡和外部存儲的路徑

用進度條顯示下載進度

拿到下載文件總長度時,設置進度條的最大值
        //設置進度條的最大值
        pb.setMax(length);
進度條需要顯示三條線程的整體下載進度,所以三條線程每下載一次,就要把新下載的長度加入進度條
定義一個int全局變量,記錄三條線程的總下載長度
            int progress;
* 刷新進度條
            while((len = is.read(b)) != -1){
                raf.write(b, 0, len);

                //把當前線程本次下載的長度加到進度條裡
                progress += len;
                pb.setProgress(progress);
每次斷點下載時,從新的開始位置開始下載,進度條也要從新的位置開始顯示,在讀取緩存文件獲取新的下載開始位置時,也要處理進度條進度
        FileInputStream fis = new FileInputStream(file);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        String text = br.readLine();
        int newStartIndex = Integer.parseInt(text);

        //新開始位置減去原本的開始位置,得到已經下載的數據長度
        int alreadyDownload = newStartIndex - startIndex;
        //把已經下載的長度設置入進度條
        progress += alreadyDownload;

添加文本框顯示百分比進度

        tv.setText(progress * 100 / pb.getMax() + %);

HttpUtils的使用

HttpUtils本身就支持多線程斷點續傳,使用起來非常的方便

創建HttpUtils對象
        HttpUtils http = new HttpUtils();
下載文件
        http.download(url, //下載請求的網址
                target, //下載的數據保存路徑和文件名
                true, //是否開啟斷點續傳
                true, //如果服務器響應頭中包含了文件名,那麼下載完畢後自動重命名
                new RequestCallBack() {//偵聽下載狀態

            //下載成功此方法調用
            @Override
            public void onSuccess(ResponseInfo arg0) {
                tv.setText(下載成功 + arg0.result.getPath());
            }

            //下載失敗此方法調用,比如文件已經下載、沒有網絡權限、文件訪問不到,方法傳入一個字符串參數告知失敗原因
            @Override
            public void onFailure(HttpException arg0, String arg1) {
                tv.setText(下載失敗 + arg1);
            }

            //在下載過程中不斷的調用,用於刷新進度條
            @Override
            public void onLoading(long total, long current, boolean isUploading) {
                super.onLoading(total, current, isUploading);
                //設置進度條總長度
                pb.setMax((int) total);
                //設置進度條當前進度
                pb.setProgress((int) current);
                tv_progress.setText(current * 100 / total + %);
            }
        });

 

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