SDWebImage源码阅读.md 7.6 KB

SDWebImage源码阅读

5.x的变化

https://github.com/SDWebImage/SDWebImage/wiki/5.0-Migration-guide

整体流程

上层API

Catergory 发起网络请求

SDWebImageManager 收集任务,根据类型不同进行分化交给不同的类

1、取消当前控件上进行的Operation

NSMapTable

为什么不用NSDictionary?

[](apple-reference-documentation://hc4k3wL7uc)```
NSDictionary  key值遵循NSCoping协议,  akey对象被copy一份后存入

如果想以对象为key,对象必须遵循NSCoping协议,实现NSMutableDictionary使用hash表来实现key和value之间的映射和存储,所以作为key值的类型必须重写\-hash 和 \-isEqual: 方法




        operations = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];

NSMapTable 可以指定option

 key值释放后,可以自动移除弱引用的value值



2、设置placeholder



3、通过SDWebImageManager去获取图片





SDWebImageCombinedOperation 包含cacheOperation和loaderOperation.





磁盘 存储 NSData 读取到内存中

NSData \-\> UIImage

png /jpeg 压缩的图片

decode解压成位图 (内存比较大、耗时 子线程)














 [SDWebImageCompat\.h](https://github.com/SDWebImage/SDWebImage/blob/09f06159a3284f6981d5495728e5c3cb3dfb82fa/SDWebImage/Core/SDWebImageCompat.h) 



#ifndef dispatch_main_async_safe #define dispatch_main_async_safe(block)

if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {\
    block();\
} else {\
    dispatch_async(dispatch_get_main_queue(), block);\
}

#endif

以前版本

#define dispatch_main_async_safe(block)

if ([NSThread isMainThread]) {\
    block();\
} else {\
    dispatch_async(dispatch_get_main_queue(), block);\
}

#endif





dispatch\_get\_main\_queue



Declaration

[](apple-reference-documentation://hcUzrK0WSn)```Return Value
Returns the main queue. This queue is created automatically on behalf of the main thread before  is called.
## Discussion
The system automatically creates the main queue and associates it with your application’s main thread. Your app uses one (and only one) of the following three approaches to invoke blocks submitted to the main queue:

   * Calling [](apple-reference-documentation://hcLi_X2d-x)

   * Calling [](apple-reference-documentation://hcwqXjGwiK) (iOS) or [](apple-reference-documentation://hcN2ZoKwK1) (macOS) 

   * Using a [](apple-reference-documentation://hcfamW1966) on the main thread
As with the global concurrent queues, calls to [](apple-reference-documentation://hc23MT12Cv), [](apple-reference-documentation://hcM68CEpXQ), [](apple-reference-documentation://hclMsqx2ga), and the like have no effect when used with queues returned by this function.

主队列的任务一定在主线程上执行

主队列伴随主线程产生

主队列是系统创建,关联到主线程中

把任务提交到主队列的三种方式

https://blog.csdn.net/li198847/article/details/104087636

SDWebImageCombinedOperation

  • cacheOpeartion
  • loaderdOpearation

面向协议

SDWebImageManager.m 中的代码

5.0前

- (nonnull instancetype)init {
    SDImageCache *cache = [SDImageCache sharedImageCache];
    SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader];
    return [self initWithCache:cache downloader:downloader];
}

5.x后

- (nonnull instancetype)init {
    id<SDImageCache> cache = [[self class] defaultImageCache];
    if (!cache) {
        cache = [SDImageCache sharedImageCache];
    }
    id<SDImageLoader> loader = [[self class] defaultImageLoader];
    if (!loader) {
        loader = [SDWebImageDownloader sharedDownloader];
    }
    return [self initWithCache:cache loader:loader];
}

SDImageCache协议

组件化时,可以单独作为一个组件,暴露SDImageCache相关接口

SDWebImageContext 是一个字典

SDWebImageContextOption是一个可扩展字符串枚举,取值如下所示:

缓存

缓存 包括 memCache和diskCache

内存缓存采用的是NSCache 和 NSMapTable结合的方式

二级缓存

weakCache

之前浏览器遇到一个问题,收到内存警告时,由于NSCache可能被系统清除,如果再访问MemoryCache时因为内存中找不到缓存就会读取磁盘缓存,可能导致闪烁的现象。weakCache可以解决这个问题,只要开始shouldUseWeakMemoryCache,weakCache保存着图片对象的弱引用,当收到内存警告时NSCache被清除,也就是取消对所有缓存image的引用,然而weakCache的value只是弱引用,所以只要没有其他强引用的image对象就会被释放, 被UIImageView实例强引用的image仍然保留,可以通过weakCache获取,并同步回NSCache中,这样可以有效减少磁盘IO。

typedef NSInteger SDImageFormat NS_TYPED_EXTENSIBLE_ENUM;
static const SDImageFormat SDImageFormatUndefined = -1;
static const SDImageFormat SDImageFormatJPEG      = 0;
static const SDImageFormat SDImageFormatPNG       = 1;
static const SDImageFormat SDImageFormatGIF       = 2;
static const SDImageFormat SDImageFormatTIFF      = 3;
static const SDImageFormat SDImageFormatWebP      = 4;
static const SDImageFormat SDImageFormatHEIC      = 5;
static const SDImageFormat SDImageFormatHEIF      = 6;
static const SDImageFormat SDImageFormatPDF       = 7;
static const SDImageFormat SDImageFormatSVG       = 8;

参考 UILayoutPriority

https://medium.com/@derrickho_28266/why-ns-typed-enum-is-the-future-c67ed8affe03

架构 & 设计模式

外观模式

外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。

为子系统中一组不同的接口提供统一的接口。

外观定义了上层接口,通过降低复杂度和隐藏子系统间的通信及依存关系,让子系统更易于使用。

manager 管理缓存、下载两个核心模块

  • 每个子系统层级有一个外观作为入口
  • 让它们通过其外观进行通信,可以简化它们之间的依赖关系

单例

代理模式

装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

类扩展

策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

@protocol SDWebImageOperation

- (void)cancel;

@end

所有实现该协议的对象都可以cancel,哪怕是不同类型的对象

如SDWebImageDownloaderOperation、SDWebImageCombinedOperation

我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作