前言:由于项目里面经常需要用到下载,所以封装了一个下载工具类。
实现方案: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);
}
}