加载一张网络图片流程,3 步:
- 1, 把这张网络图片,下载到本地;
这时候有了一个 Data
- 2, 对图片 Data 解码,
即拿 Data, 生成 UIImage,
- 3, 显示图片,
把生成的 UIImage, 赋给 UIImageView 的 image
nuke 的调用
let request = ImageRequest(
url: URL(string: "https://user-images.githubusercontent.com/1567433/59150453-178bbb80-8a24-11e9-94ca-fd8dff6e2a9a.jpeg")!,
processors: processors
)
var options = ImageLoadingOptions(transition: .fadeIn(duration: 0.5))
options.pipeline = pipeline
// request, 网络图片资源链接 ( 对应第一步 )
// options, 效果
// imageView, 来显示的 UIImageView, ( 对应第 3 步 )
loadImage(with: request, options: options, into: imageView)
源代码部分: 从调用来看,源代码怎么走
主线,网络请求
全局方法,调用入口
public func loadImage(with request: ImageRequestConvertible,
options: ImageLoadingOptions = ImageLoadingOptions.shared,
into view: ImageDisplayingView,
progress: ImageTask.ProgressHandler? = nil,
completion: ImageTask.Completion? = nil) -> ImageTask? {
// 判断主线程
assert(Thread.isMainThread)
// ImageViewController 是一个 manager
let controller = ImageViewController.controller(for: view)
return controller.loadImage(with: request.asImageRequest(), options: options, progress: progress, completion: completion)
}
进入下一层,
胶水层 class ImageViewController
func loadImage(with request: ImageRequest,
options: ImageLoadingOptions,
progress progressHandler: ImageTask.ProgressHandler? = nil,
completion: ImageTask.Completion? = nil) -> ImageTask? {
// 重置状态
cancelOutstandingTask()
// ...
let pipeline = options.pipeline ?? ImagePipeline.shared
// ...
// 通用的两级缓存,先查内存有无图片
// ...
// 先放占位图
task = pipeline.loadImageB(with: request, isMainThreadConfined: true, queue: .main) { [weak self] task, event in
switch event {
case .progress:
// ...
// 过程处理
case let .value(response, isCompleted):
if isCompleted {
// 完成了,展示图片
self?.handle(result: .success(response), fromMemCache: false, options: options)
completion?(.success(response))
} else {
if options.isProgressiveRenderingEnabled {
self?.handle(partialImage: response, options: options)
}
progressHandler?(response, task.completedUnitCount, task.totalUnitCount)
}
case let .error(error):
// ...
// 错误处理
}
}
return task
}
主要做事情的,
是图片下载与解码管道 class ImagePipeline
func loadImage(with request: ImageRequest,
isMainThreadConfined: Bool,
queue: DispatchQueue?,
observer: @escaping (ImageTask, Task<ImageResponse, Error>.Event) -> Void) -> ImageTask {
let request = inheritOptions(request)
// 拿相关信息,封装为ImageTask
let task = ImageTask(taskId: nextTaskId.increment(), request: request, isMainThreadConfined: isMainThreadConfined, isDataTask: false, queue: queue)
task.pipeline = self
self.queue.async {
// 开启图片任务
// observer 是上面的 event 事件代码
self.startImageTask(task, observer: observer)
}
return task
}
开启图片任务
func startImageTask(_ task: ImageTask, observer: @escaping (ImageTask, Task<ImageResponse, Error>.Event) -> Void) {
// ...
// 获取待解码的图片
tasks[task] = getDecompressedImage(for: task.request)
.subscribe(priority: task._priority) { [weak self, weak task] event in
guard let self = self, let task = task else { return }
// ...
// 事件完成,重置状态
if event.isCompleted {
self.tasks[task] = nil
}
// 拿到过程数据,传递给上一步
(task.queue ?? self.configuration.callbackQueue).async {
guard !task.isCancelled else { re