YYWebImage源碼分析

1. 網(wǎng)絡(luò)請(qǐng)求下載圖片

YY用的是NSURLConnection,這個(gè)其實(shí)可以用NSURLSession替換

2. 圖片解碼

2.1 判斷圖片格式

2.2 不同圖片格式對(duì)應(yīng)不同的顯示方式

  • JPEG, PNG, GIF都支持逐行顯示(baseline)


    image_baseline.gif
  • PNG,GIF支持隔行顯示(interlaced)


    image_interlaced.gif
  • 只有JPEG支持漸進(jìn)式加載


    image_progressive.gif

2.3 如何判斷圖片格式

取圖片數(shù)據(jù)的第一個(gè)字節(jié)

//通過圖片Data數(shù)據(jù)第一個(gè)字節(jié) 來獲取圖片擴(kuò)展名
- (NSString *)contentTypeForImageData:(NSData *)data{
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        case 0xFF:
            return @"jpeg";
        case 0x89:
            return @"png";
        case 0x47:
            return @"gif";
        case 0x49:
        case 0x4D:
            return @"tiff";
        case 0x52:
            if ([data length] < 12) {
                return nil;
            }
            NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
            if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                return @"webp";
            }
            return nil;
    }
    return nil;
}

2.4 圖片緩存設(shè)置

NSURLRequest 有個(gè) cachePolicy 屬性,它根據(jù)以下常量指定了請(qǐng)求的緩存行為:

  • NSURLRequestUseProtocolCachePolicy: 對(duì)特定的 URL 請(qǐng)求使用網(wǎng)絡(luò)協(xié)議中實(shí)現(xiàn)的緩存邏輯。這是默認(rèn)的策略。
  • NSURLRequestReloadIgnoringLocalCacheData:數(shù)據(jù)需要從原始地址加載。不使用現(xiàn)有緩存。
  • NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不僅忽略本地緩存,同時(shí)也忽略代理服務(wù)器或其他中間介質(zhì)目前已有的、協(xié)議允許的緩存。
  • NSURLRequestReturnCacheDataElseLoad:無(wú)論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請(qǐng)求所對(duì)應(yīng)的數(shù)據(jù),那么從原始地址加載數(shù)據(jù)。
  • NSURLRequestReturnCacheDataDontLoad:無(wú)論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請(qǐng)求所對(duì)應(yīng)的數(shù)據(jù),那么放棄從原始地址加載數(shù)據(jù),請(qǐng)求視為失?。矗骸半x線”模式)。
  • NSURLRequestReloadRevalidatingCacheData:從原始地址確認(rèn)緩存數(shù)據(jù)的合法性后,緩存數(shù)據(jù)就可以使用,否則從原始地址加載。

如果你需要更精確的緩存策略,NSURLSessionDataDelegate代理里的URLSession:dataTask:willCacheResponse:completionHandler:方法或者NSURLConnection的connection:willCacheResponse:可以實(shí)現(xiàn)

2.5 為什么用pthread_mutex_lock對(duì)圖片原始處理時(shí)加鎖,怎么使用?

之所以用pthread_mutex_lock是因?yàn)閐ispacth_semaphore無(wú)法解決遞歸調(diào)用問題,同時(shí)性能上NSRecursiveLock也沒有它好,而處理圖片二進(jìn)制數(shù)據(jù)對(duì)性能有一定要求,所以用pthread_mutex_lock
YYWebImage的源碼如下

- (instancetype)initWithScale:(CGFloat)scale {
    self = [super init];
    if (scale <= 0) scale = 1;
    _scale = scale;
    _framesLock = dispatch_semaphore_create(1);
    
    pthread_mutexattr_t attr;
    pthread_mutexattr_init (&attr);
    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);//設(shè)置鎖為遞歸鎖
    pthread_mutex_init (&_lock, &attr);
    pthread_mutexattr_destroy (&attr);
    
    return self;
}
- (BOOL)updateData:(NSData *)data final:(BOOL)final {
    BOOL result = NO;
    pthread_mutex_lock(&_lock);
    result = [self _updateData:data final:final];
    pthread_mutex_unlock(&_lock);
    return result;
}

關(guān)于pthread_mutex_lock 的使用詳見這里

2.6 PNG圖片的解碼

對(duì)于png,作者是拿到全部數(shù)據(jù)后再渲染,我之前做過一個(gè)邊拿數(shù)據(jù)邊渲染的測(cè)試,結(jié)果很耗資源;而jpeg圖片,則是邊拿到數(shù)據(jù)邊渲染

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 現(xiàn)在分析到Y(jié)YImage 首先看文件 YYImage YYFrameImage YYSpriteSheetImag...
    充滿活力的早晨閱讀 2,720評(píng)論 0 3
  • 底層使用NSUrlConnection方式,多線程異步加載網(wǎng)絡(luò)圖片; 加載時(shí)先從內(nèi)存緩存區(qū)尋找,再?gòu)拇疟P緩存區(qū)尋找...
    sea777777閱讀 1,169評(píng)論 0 2
  • 方法/步驟 打開項(xiàng)目,將左側(cè)項(xiàng)目目錄結(jié)構(gòu)排序方式選擇為Android 按照?qǐng)D示步驟操作,看不清楚請(qǐng)點(diǎn)擊大圖 在An...
    伊滴墨閱讀 466評(píng)論 0 8
  • 最近感覺得憂郁癥了,一個(gè)沒有五官的女人坐了下來。 我詫異,直勾勾盯著她的臉,半響,原來是其臉上抹了一層又白又厚的粉...
    怪奇驚選集閱讀 255評(píng)論 0 5

友情鏈接更多精彩內(nèi)容