Android的多线程网络下载的工具类

Android的多线程网络下载的工具类

在这个代码中:

  1. MultiThreadDownloader类是主要的下载类。构造函数接受要下载文件的 URL、保存文件的路径以及下载线程的数量。
  2. download方法中,首先获取文件的总大小,创建保存文件(如果不存在),然后计算每个线程需要下载的文件大小范围。
  3. 每个DownloadTask表示一个下载线程的任务,它通过设置Range请求头来请求文件的一部分进行下载。下载完成后,通过CountDownLatch来协调所有线程完成下载任务。
  4. MainActivity中的示例代码演示了如何创建MultiThreadDownloader类并启动下载过程。
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreadDownloader {

    private static final String TAG = "MultiThreadDownloader";
    private static final int BUFFER_SIZE = 8192;
    private String urlStr;
    private String saveFilePath;
    private int threadNum;

    public MultiThreadDownloader(String urlStr, String saveFilePath, int threadNum) {
        this.urlStr = urlStr;
        this.saveFilePath = saveFilePath;
        this.threadNum = threadNum;
    }

    public void download() {
        try {
            URL url = new URL(urlStr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            int fileLength = connection.getContentLength();

            File file = new File(saveFilePath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            raf.setLength(fileLength);
            raf.close();

            int partLength = fileLength / threadNum;
            CountDownLatch latch = new CountDownLatch(threadNum);
            ExecutorService executor = Executors.newFixedThreadPool(threadNum);

            for (int i = 0; i < threadNum; i++) {
                long start = i * partLength;
                long end = (i == threadNum - 1)? fileLength - 1 : (i + 1) * partLength - 1;
                DownloadTask task = new DownloadTask(start, end, latch);
                executor.execute(task);
            }

            latch.await();
            executor.shutdown();
            Log.d(TAG, "Download completed.");
        } catch (IOException | InterruptedException e) {
            Log.e(TAG, "Download error: " + e.getMessage());
        }
    }

    private class DownloadTask implements Runnable {

        private long start;
        private long end;
        private CountDownLatch latch;

        public DownloadTask(long start, long end, CountDownLatch latch) {
            this.start = start;
            this.end = end;
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(urlStr);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Range", "bytes=" + start + "-" + end);
                connection.connect();

                InputStream inputStream = connection.getInputStream();
                File file = new File(saveFilePath);
                RandomAccessFile raf = new RandomAccessFile(file, "rw");
                raf.seek(start);

                byte[] buffer = new byte[BUFFER_SIZE];
                int length;
                while ((length = inputStream.read(buffer))!= -1) {
                    raf.write(buffer, 0, length);
                }

                raf.close();
                inputStream.close();
                Log.d(TAG, "Thread finished downloading its part.");
                latch.countDown();
            } catch (IOException e) {
                Log.e(TAG, "Thread download error: " + e.getMessage());
            }
        }
    }
}

以下是使用示例:

public class MainActivity extends AppCompatActivity {

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

        String url = "http://example.com/your_file.zip";
        String savePath = getExternalFilesDir(null).getAbsolutePath() + "/your_file.zip";
        int threadCount = 3;

        MultiThreadDownloader downloader = new MultiThreadDownloader(url, savePath, threadCount);
        downloader.download();
    }
}

请注意:

  1. 这只是一个简单的示例,实际应用中可能需要更多的错误处理,例如处理网络连接失败、服务器错误等。
  2. 在 Android 6.0 及以上版本,可能需要处理运行时权限,特别是当保存文件到外部存储时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值