移动开发狂热者(299402133)

Android批量处理上传和下载

2021-09-08  本文已影响0人  客观开发者

效果图

GIF 2021-9-8 10-25-13.gif
GIF 2021-9-8 14-11-24.gif

部分源码和理解说明

一个基于okhttp的文件下载、上传工具

下载:支持多线程、断点续传下载,以及下载管理原理、以及用法

上传:支持表单形式上传、直接将文件作为请求体上传原理、以及用法

批量下载

image.png

这些就是简单类的方法了。
先串联起来就必须有简单单个下载方式。


image.png

这样就是一个简单的方式了。
通过这个思路继续下去,开始批量,进行梳理。

同单例来保障数据获取和下载的独立性

 private volatile static DownloadManger downloadManager;

    public static DownloadManger getInstance(Context context) {
        if (downloadManager == null) {
            synchronized (DownloadManger.class) {
                if (downloadManager == null) {
                    downloadManager = new DownloadManger(context);
                }
            }
        }
        return downloadManager;
    }

    private DownloadManger(Context context) {
        this.context = context;
    }

用DBuilder 来封装获取数据来源问题进行统一。
DownloadProgressHandler 来进行 Handler 数据进行回到和梳理。
FileTask 和ThreadPool 来进行真正的下载功能,在task是一个run方式,对于,每次下载还进处理并记录,从而可以导向的进行每个下载的文件进行合理的显示。

/**
     * data + callback 形式直接开始下载
     *
     * @param downloadData
     * @param downloadCallback
     * @return
     */
    public DownloadManger start(DownloadData downloadData, DownloadCallback downloadCallback) {
        execute(downloadData, downloadCallback);
        return downloadManager;
    }

这个是先通过进行分配和添加,导致可以进行合理的分配处理下载的进度。
然后在进行分离开。

 /**
     * 根据url开始下载(需先注册监听)
     *
     * @param url
     */
    public DownloadManger start(String url) {
        execute(downloadDataMap.get(url), callbackMap.get(url));
        return downloadManager;
    }

    /**
     * 注册监听
     *
     * @param downloadData
     * @param downloadCallback
     */
    public synchronized void setOnDownloadCallback(DownloadData downloadData, DownloadCallback downloadCallback) {
        downloadDataMap.put(downloadData.getUrl(), downloadData);
        callbackMap.put(downloadData.getUrl(), downloadCallback);
    }

根据url开始下载(需先注册监听) 这注册的时候,就是下载码setcallback ....
这样就很好的看到了,我们下载 下载内容了。

/**
     * 执行下载任务
     */
    private synchronized void execute(DownloadData downloadData, DownloadCallback downloadCallback) {
        //防止同一个任务多次下载
        if (progressHandlerMap.get(downloadData.getUrl()) != null) {
            return;
        }

        //默认每个任务不通过多个异步任务下载
        if (downloadData.getChildTaskCount() == 0) {
            downloadData.setChildTaskCount(1);
        }

        DownloadProgressHandler downloadProgressHandler = new DownloadProgressHandler(context, downloadData, downloadCallback);
        FileTask fileTask = new FileTask(context, downloadData, downloadProgressHandler.getHandler());
        downloadProgressHandler.setFileTask(fileTask);

        downloadDataMap.put(downloadData.getUrl(), downloadData);
        callbackMap.put(downloadData.getUrl(), downloadCallback);
        fileTaskMap.put(downloadData.getUrl(), fileTask);
        progressHandlerMap.put(downloadData.getUrl(), downloadProgressHandler);

        ThreadPool.getInstance().getThreadPoolExecutor().execute(fileTask);

        //如果正在下载的任务数量等于线程池的核心线程数,则新添加的任务处于等待状态
        if (ThreadPool.getInstance().getThreadPoolExecutor().getActiveCount() == ThreadPool.getInstance().getCorePoolSize()) {
            downloadCallback.onWait();
        }
    }

这里不得不看 单例里面四个主要的静态的变量了。

private Map<String, DownloadProgressHandler> progressHandlerMap = new HashMap<>();//保存任务的进度处理对象
    private Map<String, DownloadData> downloadDataMap = new HashMap<>();//保存任务数据
    private Map<String, DownloadCallback> callbackMap = new HashMap<>();//保存任务回调
    private Map<String, FileTask> fileTaskMap = new HashMap<>();//保存下载线程

对着四个进行添加和删除的过程就行下载和完成的过程了。

增加部分

1,批量上传
批量处理方式根据批量下载思路来的,这样就必须搞清楚批量下载。然后开始着手去创建,相同的文件和类。


image.png

发现上传 不会续传,后台根本没有这样做,失败了重新上传,或者提示上传失败就完了,
省下了存数据的烦恼了。

/**
     * 根据url开始下载(需先注册监听)
     *
     * @param uploadData
     */
    public UploadManger start(UploadFile uploadData) {
        execute(uploadData, callbackMap.get(uploadData.getFile().getAbsolutePath()));
        return downloadManager;
    }

    /**
     * 注册监听
     *
     * @param uploadData
     * @param uploadCallback
     */
    public synchronized void setOnDownloadCallback(UploadFile uploadData, UploadCallback uploadCallback) {
        uploadDataMap.put(uploadData.getFile().getAbsolutePath(), uploadData);
        callbackMap.put(uploadData.getFile().getAbsolutePath(), uploadCallback);
    }

    /**
     * 执行上传任务
     */
    private synchronized void execute(UploadFile uploadData, UploadCallback uploadCallback) {
        //防止同一个任务多次上传
        if (progressHandlerMap.get(uploadData.getFile().getAbsolutePath()) != null) {
            return;
        }

        uploadDataMap.put(uploadData.getFile().getAbsolutePath(), uploadData);
        callbackMap.put(uploadData.getFile().getAbsolutePath(), uploadCallback);

        Call upload = DUtil.initFormUpload()
                .url("http://192.168.1.110:8080/file/uploadFile") 
                .addFile("file", uploadData.getFile().getName(), uploadData.getFile())
                .fileUploadBuild()
                .upload(uploadCallback);
        progressHandlerMap.put(uploadData.getFile().getAbsolutePath(), upload);
    }

这样 先简化掉线程上传,回调等问题,先进行去操作可以批上传,进行逻辑。

列表代码

image.png image.png

最后加一键批量下载


image.png
public void startAll(ArrayList<UploadFile> uploadFiles) {
        for (UploadFile bean : uploadFiles) {
            start(bean);
        }
    }
上一篇下一篇

猜你喜欢

热点阅读