首页 > 其他分享 >iOS开发基础125-深入探索SDWebImage

iOS开发基础125-深入探索SDWebImage

时间:2024-07-17 17:33:08浏览次数:12  
标签:下载 缓存 self iOS SDImageCache 125 图像 SDWebImage

SDWebImage 是一个流行的用于处理图像下载和缓存的库,广泛用于 iOS 开发中,提供了一系列方便的 API 来下载和缓存图像,以提高应用的性能和用户体验。以下是对其进行详细介绍和分析,包括其原理和底层实现。

一、SDWebImage的主要功能

  1. 图像下载和缓存:
    • 图像下载: 使用异步方式从网络上下载图像。
    • 缓存策略: 使用内存缓存和磁盘缓存来提高图像加载速度。
  2. 异步图像加载: 异步加载图像并在下载完成后刷新 UI。
  3. 解码优化: 支持不同格式的图像解码优化。
  4. GIF 支持: 支持异步下载和展示 GIF 动画。
  5. 渐进式图像加载: 支持渐进式 JPEG 图片显示。

二、SDWebImage的使用方法

基本的使用方法如下:

#import <SDWebImage/SDWebImage.h>

UIImageView *imageView = [[UIImageView alloc] init];
NSURL *imageURL = [NSURL URLWithString:@"https://example.com/image.jpg"];

[imageView sd_setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"placeholder"]];

这段代码展示了如何使用 SDWebImage 下载图像并设置占位图。

三、SDWebImage的原理和流程

  1. API 调用:
    用户调用 sd_setImageWithURL:placeholderImage: 方法,触发图像下载过程。

  2. 缓存检查:
    SDWebImage 首先检查内存缓存 (SDImageCache) 是否存在该图像。如果存在则直接使用。

  3. 磁盘缓存检查:
    如果内存缓存不存在,再检查磁盘缓存。如果存在也直接使用,并将图像存入内存缓存以备后续使用。

  4. 网络下载:
    如果缓存(内存和磁盘)都不存在,则通过 SDWebImageDownloader 进行网络下载。

  5. 下载过程中回调:
    SDWebImageDownloader 支持多个回调,包括进度回调、完成回调、失败回调等。

  6. 缓存更新:
    下载完成后,将图像存入内存缓存和磁盘缓存。

  7. UI 更新:
    最后,更新 UIImageView 的图像。

四、SDWebImage 底层实现分析

1. 核心组件

  • SDImageCache:负责内存和磁盘缓存管理。
  • SDWebImageDownloader:负责图像下载。
  • SDWebImageManager:协调 SDImageCacheSDWebImageDownloader,管理下载和缓存策略。

2. 内存缓存 (SDImageCache)

内存缓存使用 NSCache 来管理缓存图像。NSCache 是一种内存敏感的缓存机制,可以在系统内存紧张时自动清除缓存。

@interface SDImageCache : NSObject
@property (nonatomic, strong, readonly) NSCache *memCache;
// 其他属性和方法
@end

3. 磁盘缓存 (SDImageCache)

磁盘缓存使用文件系统来存储图像,并维护一个缓存目录。常见的操作包括写入、读取和清理操作。

@interface SDImageCache ()
@property (nonatomic, strong) NSString *diskCachePath;
// 其他属性和方法
@end

4. 图像下载 (SDWebImageDownloader)

SDWebImageDownloader 使用 NSURLSession 来进行图像下载,支持并发下载和下载队列管理。

@interface SDWebImageDownloader : NSObject
@property (nonatomic, strong) NSURLSession *session;
// 其他属性和方法
@end

5. 调度与管理 (SDWebImageManager)

SDWebImageManager 负责协调缓存和下载操作,并提供统一的 API 供用户调用。

@interface SDWebImageManager : NSObject
@property (nonatomic, strong) SDImageCache *imageCache;
@property (nonatomic, strong) SDWebImageDownloader *imageDownloader;
// 其他属性和方法
@end

五、重要细节和优化

1. 图像解码和优化

SDWebImage 支持图像格式的解码优化,例如解码 PNG、JPEG 和 GIF 等。通过异步解码和背景解码来提高 UI 性能。

2. 渐进式图像加载

对渐进式 JPEG 图片的支持,能够在得到部分数据时就进行显示,极大提升了用户体验。

@interface UIImageView (WebCache)
- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDExternalCompletionBlock)completedBlock;
@end

更深入的剖析

让我们更加深入地探讨 SDWebImage 的工作原理,包括重要数据结构、具体算法和多线程管理等方面

一、架构与组件

SDWebImage 的架构主要包括以下几个组件:

  1. SDWebImageManager:管理图像加载请求的核心类。
  2. SDImageCache:负责图像缓存的实现,包括内存缓存和磁盘缓存。
  3. SDWebImageDownloader:处理图像的下载。
  4. SDWebImageDownloaderOperation:具体的下载任务类。
  5. 扩展和辅助类:包括对 UIImageViewUIButton 等类的扩展,以及 SDWebImageCompatSDWebImageDecoder 等辅助类。

二、数据结构与核心算法

1. 内存缓存 (SDImageCache)

  • NSCache:内存缓存采用了 NSCache,是一种自动清除过期对象的缓存机制,比起 NSMutableDictionary 的手动维护生命周期,NSCache 更适合用来管理内存缓存。
@interface SDImageCache ()
@property (strong, nonatomic, nonnull) NSCache *memCache;
@end
  • 构造和策略:设定一些基础的缓存限制,比如缓存数量最大值和总内存最大值。
self.memCache = [[NSCache alloc] init];
self.memCache.name = @"SDImageCache";
self.memCache.countLimit = 100;
self.memCache.totalCostLimit = 1024 * 1024 * 100; // 100 MB

2. 磁盘缓存 (SDImageCache)

  • NSFileManager:磁盘缓存主要使用 NSFileManager 来进行文件的读写操作。
@interface SDImageCache ()
@property (strong, nonatomic, nonnull) NSString *diskCachePath;
@property (strong, nonatomic, nonnull) dispatch_queue_t ioQueue;
@end
  • 队列与异步操作:为了不阻塞主线程,磁盘 I/O 操作通常在一个独立的队列中执行。
self.ioQueue = dispatch_queue_create("com.hackemist.SDImageCache", DISPATCH_QUEUE_SERIAL);
  • 路径与文件管理:将图像数据写入指定的缓存路径,并根据 URL 生成唯一的文件名。
- (NSString *)cachedFileNameForKey:(NSString *)key {
    // Hashing the key to generate a unique file name
    const char *str = [key UTF8String];
    unsigned char r[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (CC_LONG)strlen(str), r);
    NSString *filename = [NSString stringWithFormat:
                          @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                          r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[14],r[15]];
    return filename;
}

3. 图像下载 (SDWebImageDownloader)

  • NSURLSession:图像下载使用 NSURLSession 完成。对于每一个图像下载任务,SDWebImage 封装成 SDWebImageDownloaderOperation
@interface SDWebImageDownloader ()
@property (strong, nonatomic, nonnull) NSOperationQueue *downloadQueue;
@property (strong, nonatomic, nonnull) NSURLSession *session;
@end
  • 配置和队列:初始化 NSURLSession 和下载队列。
- (instancetype)init {
    self = [super init];
    if (self) {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
        self.downloadQueue = [[NSOperationQueue alloc] init];
    }
    return self;
}

- (void)dealloc {
    [self.session invalidateAndCancel];
    self.session = nil;
}

4. 图像加载管理 (SDWebImageManager)

  • 缓存与下载协调者SDWebImageManager 协调图像缓存和下载,并提供统一的 API。
- (void)loadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDInternalCompletionBlock)completedBlock {
    // First try to get image from cache
    [self.imageCache queryCacheOperationForKey:key done:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) {
        // If image is found in cache, complete immediately
        if (cachedImage) {
            [self callCompletionBlockForCompletion:completedBlock image:cachedImage data:cachedData error:nil cacheType:cacheType finished:YES url:url];
            return;
        }
        // If not found in cache, download from network
        [self downloadImageWithURL:url options:options progress:progressBlock completed:completedBlock];
    }];
}

三、多线程管理

1. 内存和磁盘缓存的线程安全

  • 内部队列SDImageCache 中为了保证线程安全性,内存缓存使用 NSCache 本身的线程安全性,而磁盘缓存则使用串行队列 ioQueue
dispatch_async(self.ioQueue, ^{
    // Disk I/O operations
});

2. 下载操作的异步处理

SDWebImageDownloader 使用 NSURLSession 的代理方法进行异步下载,并将任务加入队列执行。

@interface SDWebImageDownloaderOperation : NSOperation <NSURLSessionDataDelegate, NSURLSessionTaskDelegate>
@property (strong, nonatomic, nonnull) NSURLSessionDataTask *dataTask;
@end

- (void)start {
    // Start the download task
    self.dataTask = [self.session dataTaskWithRequest:_request];
    [self.dataTask resume];
}

四、扩展与自定义

1. 自定义下载器和缓存器

用户可以自定义下载器和缓存器,替换默认实现:

SDWebImageDownloader *customDownloader = [SDWebImageDownloader sharedDownloader];
SDImageCache *customCache = [[SDImageCache alloc] initWithNamespace:@"customCache"];
SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:customCache downloader:customDownloader];

2. 对 UIImageView 的扩展

SDWebImageUIImageView 进行了扩展,使其支持直接加载网络图像。

@interface UIImageView (WebCache)
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder;
@end

通过以上深入分析,我们可以看到 SDWebImage 是如何通过巧妙的缓存策略、高效的下载管理、线程的合理利用及其灵活的扩展能力,实现了一个高性能且易用的图像加载框架。理解这些细节不仅能帮助开发者更好地使用 SDWebImage,还能为实现类似功能提供有价值的参考。

标签:下载,缓存,self,iOS,SDImageCache,125,图像,SDWebImage
From: https://www.cnblogs.com/chglog/p/18307902

相关文章

  • iOS开发基础124-RunLoop实现卡顿检测
    利用RunLoop实现卡顿检测的基本思路是通过监听RunLoop的状态变化来判断主线程的执行时长。如果RunLoop在某个状态停留的时间超过了预设的时间阈值,则认为发生了卡顿。在具体实现中,可以利用CFRunLoopObserver来监听RunLoop的状态变化,并记录时间差。一、卡顿检测的基本原......
  • iOS开发基础122-RunLoop
    深入探讨RunLoop的底层实现需要了解CoreFoundation框架中的CFRunLoop以及与RunLoop工作机制紧密相关的操作系统底层API。这些底层实现主要涉及到事件源、定时器和线程的调度机制。本文将深入剖析RunLoop的底层结构及其运行流程。一、RunLoop底层数据结构涉及RunLo......
  • iOS开发基础123-自动释放池
    自动释放池(AutoreleasePool)是Objective-C中用于管理内存的一个重要机制,它帮助开发者简化内存管理的工作。自动释放池的核心概念是将对象放入池中,在某个时刻由系统统一释放这些对象。这种机制在iOS和macOS的应用开发中广泛使用,尤其是在事件循环和线程运行时。为了深入理解其底层......
  • 基于java+springboot+vue实现的汽车资讯网站(文末源码+Lw)125
    基于SpringBoot+Vue的实现的汽车资讯网站系统(源码+数据库+万字Lun文+流程图+ER图+结构图+演示视频+软件包)系统功能:汽车资讯网站有管理员和用户。管理员功能有个人中心,用户管理,汽车品牌管理,价格分类管理,经销商管理,汽车信息管理,留言板管理,系统管理等。用户可以查看各种汽车信......
  • vue请求接口常用写法(axios)
    1.项目根目录下新建一个utils文件夹,并新建一个request.js文件(注意:是以axios方法请求的,所以需要先安装axios或cdn引入)安装:npmnpminstallaxios-Syarnyarnaddaxios-Scdn<scriptsrc="https://unpkg.com/axios/dist/axios.min.js"></script>&&配置代码imp......
  • iOS开发基础119-组件化
    一、引言组件化是将应用程序分解成多个独立模块的设计方法,这些模块可以单独开发、测试和维护。对于大型iOS项目,组件化能够提高开发效率、降低耦合、增加代码复用性,并且使项目更易维护。本文将详细介绍如何在iOS项目中实现组件化,包括本地组件管理和远程组件管理。二、为什么......
  • iOS开发基础120-通知与线程
    NSNotificationCenter是iOS和macOS开发中用于消息传递的机制,可以在多个对象之间实现解耦的事件通知。理解NSNotificationCenter的线程模型对正确使用这一工具至关重要。NSNotificationCenter的线程模型1.消息发送线程当你通过NSNotificationCenter发送消息时,消息会......
  • iOS开发基础108-Runtime
    Objective-C的Runtime是一个强大的特性,它让语言具备了很多灵活的动态能力。通过Runtime,开发者可以在运行时解析类、方法、变量,并进行动态的消息传递、方法交换等操作。以下将详细介绍Runtime,包括具体的应用场景和底层实现原理。什么是RuntimeRuntime是Objective-C运行......
  • iOS开发基础117-Hybrid
    HybridHybrid(混合)开发是一种结合了Web技术和原生应用开发技术的方法,旨在简化跨平台应用开发。通过Hybrid开发,开发者可以用HTML、CSS和JavaScript等前端技术编写代码,并将其运行在一个内嵌的浏览器环境中,从而实现跨平台的移动应用。什么是Hybrid开发?Hybrid开发主要是指将应用的用......
  • iOS开发基础116-性能监控
    在iOS开发中,性能监控是确保应用流畅运行和用户体验的关键。常用的性能监控工具能够帮助开发者实时监控系统性能,检测和诊断性能问题。下面列举几款常用的iOS性能监控工具,深入解析其底层原理、优缺点。1.InstrumentsInstruments是由Apple官方提供的用于性能分析和调试的工具。它......