下载工具类(带缓存)
前言:由于项目里面经常需要用到下载,所以封装了一个下载工具类。
实现方案:1.下载之前查找本地有没有缓存记录
2.如果有缓存记录,那么判断缓存文件是否存在,如果存在,直接回调下载结束,否则从网络下载
3.缓存的key采用文件下载url生成的md5
4.下载失败的时候删除片段文件
实现方案:1.下载之前查找本地有没有缓存记录
2.如果有缓存记录,那么判断缓存文件是否存在,如果存在,直接回调下载结束,否则从网络下载
3.缓存的key采用文件下载url生成的md5
4.下载失败的时候删除片段文件
项目链接:https://github.com/ShadowWalkerGIT/DownloadUtil.git
使用说明:只需关注DownloadManager,这是一个单例,通过DownloadManager.getInstance()获取实例,使用前设置DownloadListener;然后调用DownloadManager.download(String cacheDir,String url)进行下载即可。注:1.不用考虑缓存目录是否存在,内部已做校验,如果不存在会自动创建该缓存目录;2.下载失败后会自动删除片段文件,不用手动清理垃圾;3.在调用的地方,比如Activity onDestroy里面调用DownloadManager.release()防止内存泄漏;4.需要的权限有网络权限和存储权限,具体代码如下:
public class DownLoadManager { private static DownLoadManager mDownloadManger; private DownLoadManager() { } public static DownLoadManager getInstance() { if (null == mDownloadManger) { synchronized (DownLoadManager.class) { if (null == mDownloadManger) { mDownloadManger = new DownLoadManager(); } } } return mDownloadManger; } /** * @param cacheDir * @param url */ public void downLoad(final String cacheDir, String url) { if (TextUtils.isEmpty(cacheDir)) { if (mDownloadListener != null) { mDownloadListener.onDownloadError(new NullPointerException("缓存目录为空")); } return; } //缓存的key采用文件url生成的MD5 final String cacheKey = MD5Util.stringToMD5(url); final String fileName = url.substring(url.lastIndexOf("/"), url.length()); ACache aCache = ACache.get(MainApplication.getContext()); String filePath = aCache.getAsString(cacheKey); if (!TextUtils.isEmpty(filePath) && new File(filePath).exists()) {//已经下载好,不用下载 if (mDownloadListener != null) { mDownloadListener.onDownloadFinish(filePath); return; } } OkHttpClient okHttpClient = new OkHttpClient(); Request.Builder builder = new Request.Builder(); builder.url(url); builder.get(); Call call = okHttpClient.newCall(builder.build()); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { try { int index = fileName.lastIndexOf("."); String tempFilePath = fileName; if (index != -1) { tempFilePath = fileName.substring(0, index); } File file = new File(cacheDir + "/" + tempFilePath); if (file.exists()) { file.delete(); } } catch (Exception exception) { } if (mDownloadListener != null) { mDownloadListener.onDownloadError(e); } } @Override public void onResponse(Call call, Response response) throws IOException { ResponseBody responseBody = ProgressHelper.withProgress(response.body(), new ProgressUIListener() { //if you don't need this method, don't override this methd. It isn't an abstract method, just an empty method. @Override public void onUIProgressStart(long totalBytes) { super.onUIProgressStart(totalBytes); if (mDownloadListener != null) { mDownloadListener.onDownloadStart(totalBytes); } } @Override public void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed) { if (mDownloadListener != null) { mDownloadListener.onDownloadProgressChange(numBytes, totalBytes, percent, speed); } } //if you don't need this method, don't override this methd. It isn't an abstract method, just an empty method. @Override public void onUIProgressFinish() { super.onUIProgressFinish(); //缓存路径 ACache.get(MainApplication.getContext()).put(cacheKey, cacheDir + "/" + fileName); if (mDownloadListener != null) { mDownloadListener.onDownloadFinish(cacheDir + "/" + fileName); } } }); BufferedSource source = responseBody.source(); File fileDir = new File(cacheDir); if (!fileDir.exists()) { fileDir.mkdirs(); } File outFile = new File(fileDir, fileName); outFile.delete(); outFile.getParentFile().mkdirs(); outFile.createNewFile(); BufferedSink sink = Okio.buffer(Okio.sink(outFile)); source.readAll(sink); sink.flush(); source.close(); } }); } public static void release() { if (mDownloadManger != null) { mDownloadManger.mDownloadListener = null; } mDownloadManger = null; } private DownloadListener mDownloadListener; public void setDownloadListener(DownloadListener downloadListener) { this.mDownloadListener = downloadListener; } public interface DownloadListener { /** * 下载开始,在UI线程调用 * * @param totalBytes */ void onDownloadStart(long totalBytes); /** * 正在下载,在UI线程调用 * * @param numBytes * @param totalBytes * @param percent * @param speed */ void onDownloadProgressChange(long numBytes, long totalBytes, float percent, float speed); /** * 下载完成,在UI线程调用 * * @param filePath */ void onDownloadFinish(String filePath); /** * 下载失败 * * @param e */ void onDownloadError(Exception e); } }