IOS 列表性能優(yōu)化-圖片解碼性能優(yōu)化

前言

為什么需要對(duì)圖片進(jìn)行解碼操作?

事實(shí)上,不管是 JPEG 還是 PNG 圖片,都是一種壓縮的位圖圖形格式。只不過(guò) PNG 圖片是無(wú)損壓縮,并且支持 alpha 通道,而 JPEG 圖片則是有損壓縮,可以指定 0-100% 的壓縮比,因此,在將磁盤(pán)中的圖片渲染到屏幕之前,必須先要得到圖片的原始像素?cái)?shù)據(jù),才能執(zhí)行后續(xù)的繪制操作,這就是為什么需要對(duì)圖片解壓縮的原因。詳見(jiàn) 談?wù)?iOS 中圖片的解壓縮 IOS 中圖片格式問(wèn)題與性能優(yōu)化 iOS開(kāi)發(fā):圖片格式與性能優(yōu)化

1.圖片解碼到底有多卡?

測(cè)試方法比較簡(jiǎn)單,在一個(gè)可以tableView里面展示圖片,圖片是已經(jīng)放在本地的10張圖片,每張圖片大于1MB

代碼如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BannerTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BannerTableViewCell" forIndexPath:indexPath];
    
    // 獲取圖片
    NSInteger index = 0;
    index = indexPath.row%10;
    NSString *imageName = [NSString stringWithFormat:@"backImage%ld",(long)index];
    //UIImage *image = [UIImage imageNamed:imageName];
    
    NSString *path = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    
    cell.contentImageView.image = image; 
    return cell;
}

細(xì)心的同學(xué)可能已經(jīng)注意到了我在代碼中寫(xiě)了兩種方式加載圖片。
一種是: [UIImage imageNamed:imageName]
一種是: [UIImage imageWithContentsOfFile:path]
后面我再解釋為什么需要對(duì)比這兩種加載方式,先上加載的結(jié)果吧。

1>使用[UIImage imageWithContentsOfFile:path]

image.png

2>使用[UIImage imageNamed:imageName]

image.png

兩種方式都實(shí)際滑動(dòng)一分鐘, 可以清晰的看到,兩種加載方式一開(kāi)始都幀數(shù)很低,但是使用imageNamed: 的很快幀數(shù)就恢復(fù)到60幀,但是使用imageWithContentsOfFile:會(huì)一直卡頓,那是因?yàn)槭褂胕mageNamed: 會(huì)緩存圖片,但是imageWithContentsOfFile: 則不會(huì),而且 使用imageWithContentsOfFile: 出現(xiàn)了明顯的卡頓,出現(xiàn)了明顯的丟幀從曲線上來(lái)看能明顯看到兩種方式的差異問(wèn)題。

再來(lái)解釋我們使用的兩種加載方式,使用 imageWithContentsOfFile: 實(shí)際上是模擬網(wǎng)絡(luò)下載圖片到本地后,再?gòu)谋镜丶虞d展示圖片的過(guò)程,imageNamed:方式則是模擬從Assets.xcassets 里加載圖片的情況,可以明顯看到蘋(píng)果是對(duì)從Assets.xcassets 里加載圖片做過(guò)優(yōu)化的。

2.如何對(duì)圖片解碼部分進(jìn)行優(yōu)化

方案很簡(jiǎn)單: 解碼的過(guò)程是可以直接放在子線程中的,解碼完成后可以在主線程中將圖片賦值給imageView.image并且緩存下來(lái),下次再次查找到相同的圖片直接在緩存中讀取就可以了。
這個(gè)過(guò)程是不是聽(tīng)起來(lái)很熟悉,是的,這個(gè)過(guò)程已經(jīng)有很有多的第三方庫(kù)實(shí)現(xiàn)過(guò)了,其中最有名的就是SDWebImage了,SDWebImage的解碼方法是decodedImageWithImage,使用了CGContextDrawImage,有興趣的小伙伴們可以抽空去看看,在這我就不贅述了,直接上優(yōu)化代碼:

    [self queryImageCache:imageName block:^(UIImage *image) {
        cell.contentImageView.image = image;
    }];

- (void)queryImageCache:(NSString *)filename block:(void(^)(UIImage *image))block
{
    //從內(nèi)存去取,如果沒(méi)取到,就直接讀取文件,在緩存起來(lái)
    UIImage *image = [self.memCache objectForKey:filename];
    if(image)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            if(block)
                block(image);
        });
    }
    else
    {
        //把解壓操作放到子線程
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:@"jpg"];
            UIImage *image = [UIImage imageWithContentsOfFile:path];
            
            image = [UIImage decodedImageWithImage:image];
            [self.memCache setObject:image forKey:filename];
            
            // 同步主線程
            dispatch_async(dispatch_get_main_queue(), ^{
                if(block)
                    block(image);
            });
       });
    }
}

實(shí)驗(yàn)以上方法后再次進(jìn)行之前的方法查看FPS和CPU使用情況


image.png
名稱(chēng) FPS (平均) CPU(平均) 實(shí)驗(yàn)時(shí)間
imageWithContentsOfFile: 47.8 28% 1min
imageNamed: 58.8 10% 1min3
優(yōu)化后 59.9 7% 1min9

可以明顯看到不論是幀數(shù)還是CPU使用情況,優(yōu)化后的列表情況都明顯優(yōu)異多了,雖然這個(gè)過(guò)程SDWebImage已經(jīng)實(shí)現(xiàn)了,但是放在我還是想放在這里來(lái)講解下,希望對(duì)各位有所幫助。

參考過(guò)以下大大的技術(shù)博客:
https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/
http://www.itdecent.cn/p/f9ef5dba9ba3?_dt_push=1
http://www.cocoachina.com/cms/wap.php?action=article&id=24599

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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