此类的方便之处在于,如果想添加新的缓存目录,只需要在DirType中增加一个新的类型即可,当然需要指定新建目录的名称和父目录(要已经存在)的名称
import android.content.Context;
import android.os.Environment;
import android.support.annotation.Nullable;
import com.lidroid.xutils.db.annotation.NotNull;
import junit.framework.Assert;
import .R;
import .utils.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created by xiaoyee on 7/12/15.
* 缓存管理工具类
*
* 如若想添加缓存路径,则在{@link .constants.IYDCache.DirType DirType}中添加对应的类型
*
*/
public class IYDCache {
private static final String TAG = "IYDCache";
public static final String CACHE_ROOT = "root_cache";
public static final String CACHE_VIDEO = "video_cache";
public static final String CACHE_IMAGE = "image_cache";
public static final String CACHE_VIDEO_MATERIAL = "material_cache";
//TODO 此项待修改
private static String mCacheDir;
private static String mPicCachePath;
private static String ROOT_DIR;
/**
* 存储所有的缓存文件路径
*
*
* key--{@link DirType#dirName() DirType的dirName方法返回值}
* value--完整路径,如 /storage/emulated/0/Android/root_cache/video_cache
*
*
*/
private static HashMap mCacheDirBox = new HashMap<>();
/**
* 第一次因为父目录未先初始化而失败的类型
*/
private static List mInitFailedDirType = new ArrayList<>();
/**
* 一般文件的前缀,如视频文件名为"iydXXXX.mp4"
*/
private static final String IYD = "iyd";
/**
* 是否成功初始化
*/
private static boolean mIsInited = false;
/**
* 文件类型
*/
public enum FileType {
PNG(".png"),
JPG(".jpg"),
MP4(".mp4");
/**
* 后缀名
*/
final String mSuffix;
FileType(String suffix) {
this.mSuffix = suffix;
}
/**
* 获取后缀名
*
* @return 指定类型的后缀名,如'.mp4'
*/
public String suffix() {
return this.mSuffix;
}
}
/**
* 根据缓存类型,缓存文件类型以及其url获取此项该有的完整路径,如"/storage/emulated/0/Android/root_cache/video_cache/iyd1736054267.mp4"
*
* @param type 缓存类型。 此处用枚举,目的是确保想用的缓存路径已经添加了,如果没有记得添加
* @param url 缓存目标的url,如图片对应的链接
* @param fileType 文件类型,如mp4,png等,如需扩展,请在{@link .constants.IYDCache.FileType FileType}中添加
* @return 结果形如 /storage/emulated/0/Android/root_cache/video_cache/iyd1736054267.mp4
*/
public static String getFileNameWithPath(DirType type, String url, FileType fileType) {
return getIYDCacheDirThisType(type) + File.separator + generateNameFromUrl(url, fileType);
}
/**
* 根据url生成文件名,此处保证如果url相同,那么返回值也相同
*
* //NOTE: 注意:此文件名含有后缀
*
*
* 实际是 " iyd + url的哈希值 + 后缀名 " 的拼接
*
*
* @param url 目标对应的url
* @param fileType 文件类型
* @return 结果形如 iyd1736054267.mp4
*/
public static String generateNameFromUrl(String url, FileType fileType) {
if (StringUtils.isBlank(url)) {
return StringUtils.empty();
}
return IYD + url.hashCode() + fileType.suffix();
}
/**
* 根据哈希值,生成文件名 无后缀名
*
* @param hashcode 目标哈希值
* @return 返回结果形如 iyd1736054267
*/
public static String generateNameFromHashcode(int hashcode) {
return IYD + hashcode;
}
/**
* 基于对象,生成文件名;无后缀名
*
* 此处目的是保证同一个对象,返回同样的文件名,但是依赖于对象的equal方法和hashCode方法
*
*
* @return 返回结果形如 iyd1736054267
*/
public static String generateNameFromObj(Object obj) {
return IYD + obj.hashCode();
}
/**
* 获取指定缓存类型的 缓存文件夹
*
* 注意,返回值可以为空
*
*
* @param type 缓存类型 {@link .constants.IYDCache.DirType}
* @return 形如"/storage/emulated/0/Android/root_cache/video_cache"或“/storage/emulated/0/Android/root_cache”
*/
@Nullable
public static String getIYDCacheDirThisType(DirType type) {
if (!mIsInited) {
throw new IllegalArgumentException(ResourceUtils.getString(R.string.not_init) + "确保在application中调用了本类的initCacheDir方法");
}
String key = type.dirName();
if (mCacheDirBox.containsKey(key)) {
return mCacheDirBox.get(key);
} else {
LogCus.e(TAG, "没找到与此对应的目录" + key);
return StringUtils.empty();
}
}
/**
* 清空指定缓存文件夹中的所有内容
* @param dirType 指定缓存文件夹类型 对应{@link .constants.IYDCache.DirType DirType}
*/
public static void clearCacheThisDir(final DirType dirType) {
new Thread(
new Runnable() {
@Override
public void run() {
FileUtils.clearDir(getIYDCacheDirThisType(dirType));
}
}
).start();
}
/**
* 初始化所有缓存文件夹,应该在application的onCreate方法中调用
*/
public static void initCacheDir(Context context) {
if (!SDCardUtil.isSDCardExist()) {
ToastUtils.show(context, ResourceUtils.getString(R.string.check_memory_is_ok));
return;
}
File androidDir = Environment.getExternalStoragePublicDirectory("Android");
ROOT_DIR = androidDir.getAbsolutePath();
mIsInited = true;
//初始化所有缓存文件夹
DirType[] allDirType = DirType.values();
for (DirType dirType : allDirType) {
initDirWithParentDirType(dirType);
}
//初始化失败的那些
for (DirType dirType : mInitFailedDirType) {
initDirWithParentDirType(dirType);
}
}
private static void initDirWithParentDirType(DirType childDir) {
String parentDirPath;
//TODO 先后问题,如果父目录未初始化时,先初始化了子目录。。。
//获取父目录文件夹路径
if (childDir == DirType.ROOT) {
//如果是根目录,那么直接定义
if (StringUtils.isBlank(ROOT_DIR)) {
throw new IllegalArgumentException("请先初始化根目录,也就是先调用 ROOT_DIR = androidDir.getAbsolutePath(); ");
}
parentDirPath = ROOT_DIR;
} else {
//否则,直接设置;父目录文件夹完整路径,应该通过 父目录对应的目录名获得
parentDirPath = mCacheDirBox.get(childDir.parentDirType().dirName());
}
LogCus.d("父路径>>>" + parentDirPath);
if (StringUtils.isBlank(parentDirPath) || !parentDirPath.contains(ROOT_DIR)) {
mInitFailedDirType.add(childDir);
return;
}
String dirPath = spliceSeparator(parentDirPath, childDir.dirName());
if (!FileUtils.isFolderExistOrCreateSuccess(dirPath)) {
LogCus.d("初始化文件夹失败" + dirPath);
return;
}
mCacheDirBox.put(childDir.dirName(), dirPath);
}
private static String spliceSeparator(String... dir) {
StringBuilder result = new StringBuilder();
for (String s : dir) {
result.append(s);
result.append(File.separator);
}
return result.toString();
}
public static String getCacheDir() {
return mCacheDir;
}
public static void setCacheDir(String mCacheDir) {
IYDCache.mCacheDir = mCacheDir;
}
/**
* 缓存文件夹类型,//NOTE: 确保添加进来的类型,其dir与parentDir路径在此类中定义
*
* 要注意此枚举类型中的顺序,父目录一定要写在子目录之前
*
*/
public enum DirType {
/**
* 缓存根目录 iyd_cache
*/
ROOT(CACHE_ROOT, ROOT_DIR),
/**
* 视频缓存目录 video_cache; 其父目录为 CACHE_ROOT
*/
VIDEO(CACHE_VIDEO, CACHE_ROOT),
/**
* 图片缓存目录 image_cache; 其父目录为 CACHE_ROOT
*/
IMAGE(CACHE_IMAGE, CACHE_ROOT),
/**
* 素材缓存目录 material_cache; 其父目录为 CACHE_ROOT
*/
MATERIAL(CACHE_VIDEO_MATERIAL, CACHE_ROOT),;
private String mDir;
private String mParentDir;
public String getParentDir() {
return mParentDir;
}
/**
* @param dir 当前目录名
* @param parentDir 父目录名
*/
DirType(String dir, String parentDir) {
this.mDir = dir;
this.mParentDir = parentDir;
}
public void setParentDir(String parentDir) {
this.mParentDir = parentDir;
}
/**
* 获取缓存文件夹名称,如video_cache
*
* @return 返回结果形如 video_cache
*/
public String dirName() {
return mDir;
}
/**
* 获取父目录的DirType,调用此方法时,一定确保其不是ROOT
*/
public DirType parentDirType() {
DirType[] dirTypes = DirType.values();
for (DirType dirType : dirTypes) {
//此项的父目录,和某项的当前目录对应
if (mParentDir.equals(dirType.dirName())) {
return dirType;
}
}
throw new IllegalArgumentException("没找到对应的父文件夹>>>" + mParentDir + ";1、请确保已经添加了并且mParentDir是对应的;2、一定确保调用此方法的类型不是ROOT");
}
}
}
清空文件夹中的方法
/**
* removes subdirectories and their contents
*/
static void purgeDirectory(File dir) {
for (File file: dir.listFiles()) {
if (file.isDirectory()) purgeDirectory(file);
file.delete();
}
}
/**
* 清空文件夹中的内容,包括子目录
* @param path
*/
public static void clearDir(String path) {
//LogCus.d("删除" + path + "目录下的所有内容");
if (StringUtils.isBlank(path)) {
return;
}
File file = new File(path);
purgeDirectory(file);
}