美文网首页
SDWebImage学习

SDWebImage学习

作者: hehc08 | 来源:发表于2019-01-19 17:59 被阅读0次

    sdwebimage

    SDWebImage 如何区分图片格式?
    将数据data转为十六进制数据,取第一个字节数据进行判断

    SDWebImage 缓存图片的名称如何避免重名
    对『绝对路径』进行MD5

    SDWebImage 如何保证UI操作放在主线程中执行?

    // SDWebImageCompat.h 中
    
    #ifndef dispatch_main_async_safe
    #define dispatch_main_async_safe(block)\
        if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\
            block();\
        } else {\
            dispatch_async(dispatch_get_main_queue(), block);\
        }
    #endif
    

    分析:如何判断当前是否在main thread?

    某些api不仅依赖于主线程上的运行,而且还依赖于主队列,因此检查当前队列而不是检查当前线程更安全。

    GCD没有一个非常方便的API来检查我们当前正在运行的队列(这很可能是许多开发人员首先使用NSThread.isMainThread()的原因)。

    我们需要使用 dispatch_queue_set_specific 函数来将键值对与主队列相关联;稍后,我们可以使用 dispatch_queue_get_specific 来检查键和值的存在。

    更安全的方法二 (SDWebImage使用的方法)

    我们知道在使用 GCD 创建一个 queue 的时候会指定 queue_label,可以理解为队列名,就像下面:

    dispatch_queue_t myQueue = dispatch_queue_create
    ("com.apple.threadQueue", DISPATCH_QUEUE_SERIAL);
    

    而第一个参数就是 queue_label,根据官方文档解释,这个queueLabel 是唯一的,所以SDWebImage就采用了这个方式

    //取得当前队列的队列名
    dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
       
    //取得主队列的队列名
    dispatch_queue_get_label(dispatch_get_main_queue())
    
    然后通过 strcmp 函数进行比较,如果为0 则证明当前队列就是主队列。
    

    SDWebImage 的Memory缓存和Disk缓存是用什么实现的?

    Memory缓存实现 -- AutoPurgeCache

    AutoPurgeCache』类继承自 『NSCache』

    Disk缓存实现 -- NSFileManager

    SDImageCache 的磁盘缓存是通过异步操作 NSFileManager 存储缓存文件到沙盒来实现的。

    读取Memory和Disk的时候如何保证线程安全?

    读取Memory

    NScache是线程安全的,在多线程操作中,不需要对Cache加锁。
    读取缓存的时候是在主线程进行。由于使用NSCache进行存储、所以不需要担心单个value对象的线程安全。

    读取Disk

    • 创建了一个名为 IO的串行队列,所有Disk操作都在此队列中,逐个执行!!
    @property (SDDispatchQueueSetterSementics, 
    nonatomic, nullable) dispatch_queue_t ioQueue;
    
    
    // Create IO serial queue
    _ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", 
    DISPATCH_QUEUE_SERIAL);
    
    
    • 判断当前是否是IOQueue
    - (void)checkIfQueueIsIOQueue {
        const char *currentQueueLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
        const char *ioQueueLabel = dispatch_queue_get_label(self.ioQueue);
        if (strcmp(currentQueueLabel, ioQueueLabel) != 0) {
            NSLog(@"This method should be called from the ioQueue");
        }
    }
    
    

    参考链接:
    https://www.jianshu.com/p/b8517dc833c7

    相关文章

      网友评论

          本文标题:SDWebImage学习

          本文链接:https://www.haomeiwen.com/subject/rzuzdqtx.html