Android一种限制同时下载个数的下载管理器实现

在Android开发中有时候会遇到需要对下载过程进行一些限制,比如只能同时下载一个文件或者允许同时下载N个文件的情况,但是不能让用户在下载完成一个或几个之后才能再次点击。因此需要对下载任务进行保存,在下载完一个后自动下载任务队列中的下一个。这种情况也是我在实际开发中遇到过的,因此分享出来,有些地方可能还不完善,但基本使用没有问题。

public class DownloadManager {
    private static final String TAG = "DownloadManager";
    public class DownLoadTask {
        public String url;
        public String localPath;
        public IDownloadListener listener;
    }
    private static DownloadManager mInstance = null;
    private Context mContext;
    private List<DownLoadTask> mDownloadWaitings = new ArrayList<DownLoadTask>(); //等待下载的任务
    private List<DownLoadTask> mDownLoadings = new ArrayList<DownLoadTask>(); //正在下载的任务
    private static final int MAX_NUM = 1; //正在下载的最大下载任务数
    private DownloadManager(Context context) {
        this.mContext = context;
    }
    public synchronized static DownloadManager getInstance(Context context) {
        if (null == mInstance) {
            mInstance = new DownloadManager(context);
        }
        return mInstance;
    }
    private synchronized void pushList(DownLoadTask info) {
        mDownloadWaitings.add(info);
    }
    private synchronized DownLoadTask popList() {
        if (mDownloadWaitings.size() == 0) {
            return null;
        }
        return mDownloadWaitings.remove(0);
    }
    public DownLoadTask findTask(String url){
        for(int i = 0; i < mDownloadWaitings.size(); ++ i){
            if(mDownloadWaitings.get(i).url.equals(url)){
                return mDownloadWaitings.get(i);
            }
        }
        for(int i = 0; i < mDownLoadings.size(); ++ i){
            if(mDownLoadings.get(i).url.equals(url)){
                return mDownLoadings.get(i);
            }
        }
        return null;
    }
    public synchronized boolean isDownloadWaiting(String url){
        if(mDownloadWaitings.size() == 0)return false;
        for(int i = 0; i < mDownloadWaitings.size(); ++ i){
            String murl = mDownloadWaitings.get(i).url;
            if(murl.compareTo(url) == 0){
                return true;
            }
        }
        return false;
    }
    public synchronized boolean isDownloading(String url){
        if(mDownLoadings.size() == 0)return false;
        for(int i = 0; i < mDownLoadings.size(); ++ i){
            String murl = mDownLoadings.get(i).url;
            if(murl.compareTo(url) == 0){
                return true;
            }
        }
        return false;
    }
    public synchronized boolean isDownloadingOrWaiting(String url){
        List<DownLoadTask> loadingOrWaitingList = new ArrayList<DownLoadTask>();
        loadingOrWaitingList.addAll(mDownloadWaitings);
        loadingOrWaitingList.addAll(mDownLoadings);
        if(loadingOrWaitingList.size() == 0)return false;
        for(int i = 0;i < loadingOrWaitingList.size(); ++ i){
            String murl = loadingOrWaitingList.get(i).url;
            if(murl.compareTo(url) == 0){
                return true;
            }
        }
        return false;
    }
    public synchronized boolean isDownloading(){
        if(mDownLoadings.size() != 0)
            return true;
        return false;
    }
    /**
     * 取消下载任务
     */
    public void cancelTask(DownLoadTask task) {
        if(task == null){
            return;
        }
        if (mDownloadWaitings.contains(task)) {
            Log.d(TAG, "cancelTask() waiting");
            // 下载任务排队中,删除任务;
            mDownloadWaitings.remove(task);
        } else {
            Log.d(TAG, "cancelTask() loading. task.url: " + task.url);
            cancelDownloadingTask(task);
        }
    }
    public void cancelAllTask(){
        mDownloadWaitings.clear();
        for(DownLoadTask task : mDownLoadings){
            cancelDownloadingTask(task);
        }
        mDownLoadings.clear();
    }
    private void cancelDownloadingTask(DownLoadTask task){
        HttpUtil.cancelByTag(task.url); //取消正在下载的任务
    }
    /**
     * 添加下载任务
     *
     * @param downloadUrl 下载地址
     * @param savePath    文件保存目录
     * @param listener    下载监听器
     * @return ThumbLoadTask 返回当前下载任务实例
     */
    public DownLoadTask addDownloadTask(String downloadUrl, String savePath, IDownloadListener listener) {
        synchronized (this) {
            if (TextUtils.isEmpty(downloadUrl)) {
                if (listener != null) {
                    listener.onFailure("下载地址不能为空");
                }
                return null;
            }
            if (TextUtils.isEmpty(savePath)) {
                if (listener != null) {
                    listener.onFailure("文件保存目录不能为空");
                }
                return null;
            }
            if (listener != null) {
                listener.onWaiting();
            }
            // Add it to list.
            DownLoadTask info = new DownLoadTask();
            info.url = downloadUrl;
            info.localPath = savePath;
            info.listener = listener;
            pushList(info);
            return info;
        }
    }
    /**
     * 开始下载
     */
    public void startDownload() {
        int currNum = mDownLoadings.size();
        Log.d(TAG, "startDownload(). currNum: " + currNum);
        if(currNum < MAX_NUM) {
            DownLoadTask task = popList();
            if (task != null) {
                mDownLoadings.add(task);
                download(mContext, task);
            }
        }
    }
    private void changeLoadingByFinish(DownLoadTask task){
        mDownLoadings.remove(task);
    }
    private void download(Context context, final DownLoadTask task) {
        String url = task.url;
        String localFilePath = task.localPath;
        final IDownloadListener listener = task.listener;
        Log.d(TAG, "download() begin. url: " + url);
        if (TextUtils.isEmpty(url) || TextUtils.isEmpty(localFilePath) || listener == null) {
            Log.e(TAG, "download information is not complete.");
            return;
        }
        final File file = new File(localFilePath);
        if (file.exists()) {
            Log.e(TAG, "File is already exist.");
            listener.onSuccess(file);
            return;
        }
        Object tag = url;
        new HttpEngine().downloadFile(context, url, localFilePath, new IDownloadTagListener() {
            int lastPercent = 0;
            long lastTime = 0;
            @Override
            public void onStart() {
                listener.onStart();
            }
            @Override
            public void onProgress(long bytesWritten, long totalSize) {
                int currentPercent = (int) ((bytesWritten * 100) / totalSize);
                long currentTime = System.currentTimeMillis();
                // 为防止UI刷新过快,当只有更新百分比大于百分之一 且 更新时间与上次更新时间相差大于500ms 时才进行回调
                if((currentPercent - lastPercent) > 1 && (currentTime - lastTime) > 500) {
                    listener.onProgress(bytesWritten, totalSize);
                    lastPercent = currentPercent;
                    lastTime = currentTime;
                }
            }
            @Override
            public void onSuccess(File file) {
                changeLoadingByFinish(task);
                listener.onSuccess(file);
                startDownload();
            }
            @Override
            public void onFailure(File file, String error) {
                changeLoadingByFinish(task);
                listener.onFailure(error);
                startDownload();
            }
            @Override
            public void onCancel() {
                changeLoadingByFinish(task);
                listener.onCancel();
                startDownload();
            }
        }, tag);
    }
}

public interface IDownloadListener {
    /**
     * 传输等待
     */
    public void onWaiting();
    /**
     * 传输开始
     */
    public void onStart();
    /**
     * 传输进行中
     *
     * @param totalSize   数据总量
     * @param currentSize 已下载数据量
     */
    public void onProgress(long currentSize, long totalSize);
    /**
     * 传输完成
     *
     * @param file 文件对象
     */
    public void onSuccess(File file);
    /**
     * 传输错误
     *
     * @param error 错误信息
     */
    public void onFailure(String error);
    /**
     * 取消下载
     */
    public void onCancel();
}

其中
new HttpEngine().downloadFile(context, url, localFilePath, new IDownloadTagListener(){}, tag);
方法是具体的下载方法,可以自己实现,也可以使用开源网络库进行实现,本文只讨论下载管理,对具体下载实现不做讨论。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
文件管理器一种应用程序,用于在Android设备上管理文件和文件夹。该应用程序允许用户查看、复制、剪切、粘贴、重命名和删除文件,以及在不同目录之间导航。 Android中的文件管理器代码主要涉及以下几个方面: 1. 用户界面设计:代码需要实现一个直观且易于使用的用户界面,以便用户可以轻松地浏览设备上的文件和文件夹。这通常涉及使用ListView或GridView来显示文件和文件夹列表,并添加适当的图标和文本描述。 2. 文件和文件夹的操作:代码需要处理用户对文件和文件夹的操作,例如复制、剪切、粘贴、重命名和删除等。这可以通过使用Java的File类和相应的方法来实现。 3. 目录导航:代码需要处理用户在不同目录之间导航的操作。这可以通过维护当前目录路径的变量,并在用户导航时更新该路径来实现。使用递归或栈来实现目录结构的遍历是一个常见的方法。 4. 异步操作:为了避免在UI线程上执行耗时的文件操作,代码需要使用异步任务来处理这些操作。在执行文件操作期间,可以显示进度条或其他用户界面元素来提供反馈。 除了上述主要方面,文件管理器代码还可以包括其他功能,如搜索功能、文件排序功能、文件压缩和解压缩功能等。在编写代码时,需要考虑设备的存储权限和外部存储的访问限制。 总结起来,文件管理器代码的主要目标是提供一个简单易用的用户界面,使用户能够方便地管理Android设备上的文件和文件夹。它需要处理文件和文件夹的基本操作,并提供目录导航和异步操作来提高用户体验。同时,还可以考虑其他功能来增强应用程序的功能性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值