首先声明,这篇文章不是讲getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()等等文件目录的存放位置,及使用方法的。
本文章,主要是想说下通过枚举来管理缓存目录(就是上面那么目录),是否比我们常用的常量管理缓存目录更有优势。
我们先看下Android下的缓存目录
上面就是一般,我们需要用的一些缓存数据的目录,比如配置文件,广告,数据缓存等等。
通常情况下,在管理缓存数据的目录结构的时候,我是怎么操作的呢。
- 1,首先创建一个路径管理类
- 2,然后,创建缓存目录的常量。比如,adsPath=rootPath+"/ads/";
- 3,使用时候,判断初始化,把路径引用过去。save(adsPath+xx.png)
这样做有什么不好的地方呢?
- 1,初始化缓存目录不方面,每次用的时候,都需要判断是否创建。
- 2,到处引用路径,如果管理不好,想要修改的话,会是个灾难。
- 3,缓存文件,有被修改的可能。如果,有人没有把路径写到这个类里面呢?
下面,我们尝试使用枚举来管理缓存的路径,看看是否更优雅,更有优势呢。
当然,Android不建议使用枚举,因为枚举的每个变量其实,都会生成一个对象属性,并且还会有一个包换所有属性的对象数组。这样,相比与其他常量来说会带来更大的内存消耗。但是,使用枚举来管理,也有它的优势。(不然,还写啥呢…)
使用枚举有很多优势:
- 安全
- 构造方法私有
- 管理,操作方便
比如,多账号登陆,每个账号下的缓存文件夹的功能差不多,图片,用户信息等。
这样的话,通过常量的方式来管理缓存目录,就需要不断的拼接字符串,来实现每个账号下的缓存目录,既不方便,也容易出错。
下面,就通过枚举来设计一个缓存文件夹管理的架构。看看是不是比我们常用的方式,更方便呢?
创建步骤:
- 1,创建通用的缓存文件目录
- 2,创建每个账号下的缓存路径
- 3,创建初始化缓存目录类
- 4,初始化缓存目录及效果
- 5,其他的工具类
1,创建一个通用的缓存文件目录
一般来说,图片缓存,数据缓存都是我们常用的,我们就添加这两个缓存目录
/**
* cache中缓存的文件路径
*/
public enum CommonCacheFile {
/**
* cache的图片文件路径。
*/
CACHE_IMAGE("/common/image/"),
/**
* 文件的缓存路径
*/
CACHE_FILE("/common/file/");
private String path;
CommonCacheFile(String path) {
this.path = path;
}
public String getValue() {
//缓存的根目录+缓存的相对路径
return SDCardUtils.getAppCacheFile(false) + path;
}
}
这个枚举,保存的都是我们缓存的相对路径。通过getValue()方法,来获取绝对路径。这样,控制我们的缓存路径是不是看着更加直观呢。
下面,我们为多账号登陆也设计一个枚举类。
2,创建每个账号下的缓存路径
有时候,我们需要设计多账号的缓存目录,每个账号下的缓存目录结构,基本是一样的。
这个时候,如果使用常量,是不是就没有那么方便了。
我们创建一个枚举类来实现。
public enum UserFile {
/**
* 用户信息路径
*/
fileUserInfo("/userInfo/");
private String value;
UserFile(String path) {
this.value = path;
}
public String getValue() {
//这里,我们模拟一个userId(12345)。
return SDCardUtils.getAppSubFile(false, "12345") + value;
}
}
通过上面的枚举,我们只要动态替换了"12345",就达到了多账号,缓存目录的创建。
相当于根目录+userId+缓存目录相对路径。
缓存目录的枚举创建好了之后,我们就需要在进入APP的时候,把我们的文件夹都初始化。
这样,也就避免了我们每次使用的时候需要判断的缺点。
3,创建初始化缓存目录类
我们刚进入APP的时候,就把我们需要的缓存文件目录都初始化。
这样的好处:
- 1,不用每次使用的时候,都需要判断是否初始化。
- 2,如果忘了初始化,就会造成IO异常。
public class FileEngine {
public static void init(Context applicationContext) {
SDCardUtils.init(applicationContext);
//通用的缓存目录 枚举 。通过values()获取所有的缓存目录
CommonCacheFile[] cacheFiles = CommonCacheFile.values();
//用户下的缓存目录 枚举
UserFile[] userFiles = UserFile.values();
List<String> path = new ArrayList<>();
//把所有路径,都放到集合
for (CommonCacheFile cacheFile : cacheFiles) {
path.add(cacheFile.getValue());
}
for (CommonFile cacheFile : files) {
path.add(cacheFile.getValue());
}
path.add(cacheFile.getValue());
}
//创建所有的缓存文件目录
for (String p : path) {
initDir(new File(p));
}
}
private static boolean initDir(File dir) {
return FileUtils.createDir(dir);
}
}
这里,我们通过枚举的values()方法,拿到所有的缓存目录的集合,然后,全部初始化。以后,我们枚举如果添加新的缓存目录,这里也不需要改动。
4,初始化缓存目录及效果
这里,我们就找个Activity初始化,看下效果。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//这样,我们的缓存目录就初始化好了
FileEngine.init(getApplicationContext());
}
}
这里,我们通过一行代码,所有需要的缓存目录就都初始化好了,是不是很简单。
到这里,我们的APP的缓存目录管理,就做完了。
通过枚举来管理缓存目录,确实比常量要消耗更多的内存。但是,这样我们可以更加直观的管理缓存,操作上也方便很多,尤其在多账号的时候,作用更明显。
下面看下效果
这里,我们就看到了,我们调用初始化方法后。我们的common缓存跟账户12345下面的userInfo缓存目录就已经创建好了。
如果,我们想实现多账号的缓存目录管理的话,我们只需要动态修改UserFile枚举里的 12345就可以达到目的了。
public enum UserFile {
/**
* 用户信息路径
*/
fileUserInfo("/userInfo/");
private String value;
UserFile(String path) {
this.value = path;
}
public String getValue() {
return SDCardUtils.getAppSubFile(false, "12345") + value;
}
}
只需要动态替换掉 12345这个账号,就会在对应账号下创建缓存目录了。
这样的多账号缓存设计,是不是更优雅呢。
通过枚举实现缓存目录的管理,到这里就完成了。
5,其他的工具类
FileUtil,文件工具类
public class FileUtils {
public static boolean createDir(File dir) {
if (dir == null) {
return false;
}
if (checkFileExist(dir)) {
return true;
}
return makeDir(dir);
}
private static boolean checkFileExist(File file) {
return file != null && file.exists();
}
private static boolean makeDir(File dir) {
if (dir.exists() && !dir.isFile()) {
return true;
}
return dir.mkdirs();
}
}
权限工具类
public class PermissionUtils {
private static volatile PermissionUtils sInstance;
public static final String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
private PermissionUtils() {
}
public static PermissionUtils getsInstance() {
if (sInstance == null) {
sInstance = new PermissionUtils();
}
return sInstance;
}
public boolean checkPermission(Context context, String... permissions) {
for (String permission : permissions) {
// 判断当前该权限是否允许
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 判断是否需要动态申请权限
*/
public static boolean needRequestPermission() {
return Build.VERSION.SDK_INT >= 23;
}
}
SD卡工具类,获取根目录
public class SDCardUtils {
private static Context context;
public static void init(Context application) {
context = application;
}
/**
* 获取app 的file
*/
public static String getAppFile(boolean internal) {
if (internal) {
return getAppInternalDir();
}
return getAppExternalDir();
}
/**
* 获取app 的cache File
*/
public static String getAppCacheFile(boolean internal) {
if (internal) {
return getAppInternalCacheDir();
}
return getAppExternalCacheDir();
}
/**
* 这里是提供 根目录下的二级目录
*/
public static String getAppSubFile(boolean internal, String name) {
return getAppFile(internal) + File.separator + "liu" + File.separator + name + File.separator;
}
public static String getAppInternalDir() {
return context.getFilesDir().getPath();
}
public static String getAppInternalCacheDir() {
return context.getCacheDir().getPath();
}
public static String getAppExternalDir() {
String path = "";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
&& hasSDCardPermission()) {
File fileDir = context.getExternalFilesDir(null);
if (fileDir != null) {
path = fileDir.getPath();
} else {
fileDir = context.getFilesDir();
if (fileDir != null) {
path = fileDir.getPath();
}
}
}
return path;
}
public static String getAppExternalCacheDir() {
String path = "";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
&& hasSDCardPermission()) {
File fileDir = context.getExternalCacheDir();
if (fileDir != null) {
path = fileDir.getPath() ;
} else {
fileDir = context.getFilesDir();
if (fileDir != null) {
path = fileDir.getPath();
}
}
}
return path;
}
public static boolean hasSDCardPermission() {
return (!PermissionUtils.needRequestPermission()
|| PermissionUtils.getsInstance()
.checkPermission(context, PermissionUtils.PERMISSIONS_STORAGE));
}
}