前言
在源码解析的第一篇中,咱们讲解了 Kingfisher 的最主要的功用-异步加载网络图片的流程,以及怎么规划支撑同一个类型参数能够依据 URL 类型加载本地以及网络的资源。
这一篇咱们接着来依据 Features 继续整理代码。
Useful image processors and filters provided.
Kingfisher 不只实现了下载和缓存图片,它也给咱们供给了很多 UI 方面很实用的功用。比方 Github 上面举例的 DownsamplingImageProcessor
,示例代码如下:
let processor = DownsamplingImageProcessor(size: imageView.bounds.size)
|> RoundCornerImageProcessor(cornerRadius: 20)
这一句代码能够实现下面的两个功用:
- 对其进行下采样以匹配图画视图大小。
- 使其具有给定半径的圆角。
其他的 processor 大家能够去ImageProcessor
这个文件自行查阅,这儿就不打开讲了。
Multiple-layer hybrid cache for both memory and disk.
Kingfisher 加载网络图片的时分,支撑内存和磁盘两种缓存。假如你不指定,默许情况下是图片资源在内存和磁盘中都会缓存。
内存缓存
代码如下:
func storeNoThrow(
value: T,
forKey key: String,
expiration: StorageExpiration? = nil) {
lock.lock()
defer { lock.unlock() }
let expiration = expiration ?? config.expiration
// The expiration indicates that already expired, no need to store.
guard !expiration.isExpired else { return }
let object: StorageObject<T>
if config.keepWhenEnteringBackground {
object = BackgroundKeepingStorageObject(value, expiration: expiration)
} else {
object = StorageObject(value, expiration: expiration)
}
storage.setObject(object, forKey: key as NSString, cost: value.cacheCost)
keys.insert(key)
}
首要是用 NSLock
加锁,由于图片加载是多线程异步加载的,所以需求加锁防止数据竞赛。接着是判别缓存的有效期,默许值是 300s,假如在有效期内直接返回。
接着就是缓存的操作了,这儿判别了一下 APP 是否已经退入后台,假如退入后台则运用 BackgroundKeepingStorageObject
,若没有则运用 StorageObject
。
最终,运用 NSCache
数据结构,将下载的图片资源存入内存中。需求注意的是,假如是网络加载的资源,key 默许情况下是 URL 的 absoluteString
,假如你想自定义 cacheKey 的话需求运用 ImageResource
来初始化目标,示例代码如下:
let url = URL(string: "xxx/images/kingfisher-1.jpg")!
let imageResource = KF.ImageResource(downloadURL: url, cacheKey: "hello")
磁盘缓存
代码如下:
// 磁盘缓存
public func store(
value: T,
forKey key: String,
expiration: StorageExpiration? = nil,
writeOptions: Data.WritingOptions = []) throws {
guard storageReady else {
throw KingfisherError.cacheError(reason: .diskStorageIsNotReady(cacheURL: directoryURL))
}
let expiration = expiration ?? config.expiration
// The expiration indicates that already expired, no need to store.
guard !expiration.isExpired else { return }
let data: Data
do {
data = try value.toData()
} catch {
。。。
}
let fileURL = cacheFileURL(forKey: key)
do {
try data.write(to: fileURL, options: writeOptions)
} catch {
。。。
}
let now = Date()
let attributes: [FileAttributeKey : Any] = [
// The last access date.
.creationDate: now.fileAttributeDate,
// The estimated expiration date.
.modificationDate: expiration.estimatedExpirationSinceNow.fileAttributeDate
]
do {
try config.fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
} catch {
。。。
}
maybeCachedCheckingQueue.async {
self.maybeCached?.insert(fileURL.lastPathComponent)
}
}
磁盘缓存首要判别了 storageReady 是否为true,接着判别了是否缓存已过期(磁盘缓存默许时刻是 7 天)。
前置条件都契合之后,将图片转为 Data,调用 cacheFileURL
拿到图片的磁盘途径,然后调用 write(to url: URL, options: Data.WritingOptions = [])
将其写入磁盘中。
最终,再将磁盘缓存文件的过期时刻更新为当时时刻。
Fine control on cache behavior. Customizable expiration date and size limit.
Kingfisher 不只能够支撑内存和磁盘的双重缓存,它也很人性化的供给了很多参数,让咱们能够自定义缓存的各种参数。
下面是该库支撑的缓存参数:
- forceRefresh:默许为
false
,若为true
则代表无论有没有缓存都去网络下载。 - fromMemoryCacheOrRefresh:默许为
false
,若为true
则代表不运用磁盘缓存只运用内存缓存,若内存缓存没有就去网络下载。 - cacheMemoryOnly:默许为
false
,若为true
则代表不运用磁盘缓存只运用内存缓存。 - memoryCacheExpiration: 内存缓存过期时刻设置,默许为 300秒。
- diskCacheExpiration:磁盘缓存过期时刻设置,默许为 7 天。
- memoryCacheAccessExtendingExpiration:每次访问内存缓存资源后,该资源的过期时刻延伸战略。默许是运用原缓存时刻。比方 a 图片被首次缓存,默许过期时刻是 300 秒。20 秒之后你访问了 a 图片,那 a 图片的过期时刻会重置成 300 秒。
- diskCacheAccessExtendingExpiration:磁盘的过期时刻延伸战略,默许逻辑行为同 memoryCacheAccessExtendingExpiration。