这个类呢其实是我在慕课网上看的,当然了,我自己做了些改动,还是稍稍有点不同的。
class ImageFileCacheUtils(private var context: Context?) {
constructor() : this(null){
removeCache(cacheDirectory, 0.4f, false)
}
init {
removeCache(cacheDirectory, 0.4f, false)
}
fun clearCache(): Boolean {
return removeCache(cacheDirectory, 1.0f, true)
}
/**
* 从文件缓存中获取图片
* @param url
* @return
*/
fun getImage(url: String): Bitmap? {
val path = cacheDirectory + "/" + convertUrlToFileName(url)
val file = File(path)
if (file.exists()) {
val bitmap = BitmapFactory.decodeFile(path)
if (bitmap == null) {
file.delete()
return null
} else {
updateFileTime(path)//更新文件最新访问时间
return bitmap
}
} else {
return null
}
}
/**
* 修改文件的最后修改时间
* @param path
*/
private fun updateFileTime(path: String) {
val file = File(path)
val newModeifyTime = System.currentTimeMillis()
file.setLastModified(newModeifyTime)
}
fun saveBitmap(bitmap: Bitmap?, url: String) {
if (bitmap == null) {
return
}
//判断SD卡上的空间
if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
return
}
val fileName = convertUrlToFileName(url)
val dir = cacheDirectory
val dirFile = File(dir)
if (!dirFile.exists()) {
dirFile.mkdirs()
}
val file = File("$dir/$fileName")
try {
file.createNewFile()
val outputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
outputStream.flush()
outputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
/**
* 计算sd卡上的剩余空间
* @return
*/
fun freeSpaceOnSd(): Int {
val statFs = StatFs(Environment.getExternalStorageDirectory().path)
val sdFreeMB = statFs.availableBlocks.toDouble() * statFs.blockSize.toDouble() / MB
Log.i("ImageFileCacheUtils:", "剩余空间为:$sdFreeMB")
return sdFreeMB.toInt()
}
/**
* 获取文件夹中缓存文件.cache占用存储空间大小
* @return
*/
fun cacheSizeOnSd(): Int {
val dirFile = File(cacheDirectory)
val files = dirFile.listFiles()
if (files == null || files.size <= 0) {
return 0
}
//如果sd卡没有挂载
if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED) {
return 0
}
var dirSize = 0
for (i in files.indices) {
if (files[i].name.contains(WHOLESALE_CONV)) {
dirSize += files[i].length().toInt()
}
}
return dirSize
}
/**
* 将url转成文件名
* @param url
* @return
*/
private fun convertUrlToFileName(url: String): String {
val strs = url.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
return strs[strs.size - 1] + WHOLESALE_CONV
}
/**
* 计算存储目录下的文件大小
* 当文件总大小大于规定的大小或者sd卡剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定时
* ,那么删除removeSize * 100%最近没有被使用的文件
* @param dirPath
* @return
*/
private fun removeCache(dirPath: String, removeSize: Float, isClearAll: Boolean): Boolean {
val dirFile = File(dirPath)
val files = dirFile.listFiles()
if (files == null || files.size <= 0) {
return true
}
//如果sd卡没有挂载
if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED) {
if (context != null) {
Toast.makeText(context, "检测不到外部存储空间,无法使用缓存!", Toast.LENGTH_SHORT).show()
}
return false
}
val dirSize = cacheSizeOnSd()
if (isClearAll || dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
val removeFactor: Int
if (removeSize < 1) {
removeFactor = (removeSize * files.size + 1).toInt()
} else {
removeFactor = files.size
}
Arrays.sort(files, FileLastModifySoft())
for (i in 0 until removeFactor) {
if (files[i].name.contains(WHOLESALE_CONV)) {
files[i].delete()
}
}
}
if (freeSpaceOnSd() <= CACHE_SIZE) {
if (context != null) {
Toast.makeText(context, "存储空间不足,请及时清理!", Toast.LENGTH_SHORT).show()
}
return false
}
return true
}
//比较器类
private inner class FileLastModifySoft : Comparator<File> {
override fun compare(arg0: File, arg1: File): Int {
return if (arg0.lastModified() > arg1.lastModified()) {
1
} else if (arg0.lastModified() == arg1.lastModified()) {
0
} else {
-1
}
}
}
companion object {
private val CHCHEDIR = "ImageChace"//缓存目录
val WHOLESALE_CONV = ".cache"//缓存文件后缀名
private val MB = 1024 * 1024
private val CACHE_SIZE = 80//缓存最大容量(超过就会利用lru算法删除最近最少使用的缓存文件)
private val FREE_SD_SPACE_NEEDED_TO_CACHE = 100//缓存所需SD卡所剩的最小容量
private var util: ImageFileCacheUtils = ImageFileCacheUtils()
//单例模式
fun getInstance(): ImageFileCacheUtils {
if (util == null) {
synchronized(ImageFileCacheUtils::class.java) {
if (util == null) {
util = ImageFileCacheUtils()
}
}
}
return util
}
fun getInstance(context: Context): ImageFileCacheUtils {
if (util == null) {
synchronized(ImageFileCacheUtils::class.java) {
if (util == null) {
util = ImageFileCacheUtils(context)
}
}
}
return util
}
/**
* 获得缓存目录
* @return
*/
val cacheDirectory: String
get() = "${sdPath}/${CHCHEDIR}"
private//判断SD卡是否挂载
//获取根目录
val sdPath: String
get() {
var sdDir: File? = null
val adCardExit = Environment.getExternalStorageState()
.endsWith(Environment.MEDIA_MOUNTED)
if (adCardExit) {
sdDir = Environment.getExternalStorageDirectory()
}
return if (sdDir != null) {
sdDir.toString()
} else {
""
}
}
}
}