SDWebImage
首先SDWebImage是我們經(jīng)常用的一個(gè)加載網(wǎng)絡(luò)圖片的庫(kù),內(nèi)部很好的處理了緩存、下載、解碼之間關(guān)系,使得在性能上有很大的提升。
SDWebImage大致可以分為5大塊:
我們拿UIImageView來(lái)說(shuō),入口就是
[imageView sd_setImageWithURL:nil]
- wrap結(jié)構(gòu):充分使用了單一原則和接口隔離的設(shè)計(jì)原則,UIImageView跟UIButton等空間區(qū)分開(kāi)來(lái),互相不干擾。但是他們都會(huì)走到UIView的 sd_internalSetImageWithURL方法,在這里處理相關(guān)邏輯。
- 管理:使用SDImageManage類來(lái)調(diào)節(jié)緩存跟回調(diào)之間的關(guān)系。當(dāng)接收到此URL,會(huì)先進(jìn)行取消下載,避免多次下載。作用就是調(diào)度緩存下載外層結(jié)構(gòu)之間的關(guān)系回調(diào)
- 緩存:然后sd_queryCacheOperationForKey內(nèi)部尋找緩存,先根據(jù)NSCache在內(nèi)存中查找是否存在緩存,然后在磁盤中查找緩存,這里有個(gè)小細(xì)節(jié)就是,如果在磁盤中查到緩存就將緩存存入內(nèi)存中去,如果兩個(gè)都沒(méi)有找到需要進(jìn)行下載。
- 下載:使用SDImageOperationQuque來(lái)進(jìn)行管理下載,創(chuàng)建一個(gè)任務(wù),啟動(dòng)section進(jìn)行下載,通知管理類,來(lái)處理圖片。
- 解碼:網(wǎng)絡(luò)圖片一般會(huì)偏大,對(duì)于我們的圖片渲染性能來(lái)說(shuō)是個(gè)很大的損失,所以這里講圖片進(jìn)行解碼操作,生成位圖返回新圖片,這樣在GPU渲染的時(shí)候可以直接使用位圖來(lái)進(jìn)行渲染,極大的提升性能。
然后異步將圖片存入緩存之中去。清除緩存的時(shí)候時(shí)候會(huì)將默認(rèn)1周的圖片進(jìn)行清理,避免浪費(fèi)空間。
總結(jié):通過(guò)源碼學(xué)到了作者的編程思想,設(shè)計(jì)原則體現(xiàn)的淋漓盡致,將類于類之間充分的解耦,枚舉使用位移的方式,節(jié)省內(nèi)存開(kāi)銷。下載使用Operation隊(duì)列來(lái)管理下載類,對(duì)自己以后做下載相關(guān)需求的時(shí)候很大的提升,緩存的思維,內(nèi)存報(bào)警之后的處理。圖片的解碼了解到性能上的優(yōu)化相關(guān)的操作等等。
YYCache
YYCache是我們通常使用的緩存類,當(dāng)我們做頁(yè)面緩存的時(shí)候是一個(gè)非常不錯(cuò)的選擇。
緩存分為2類,一種是內(nèi)存緩存,一種是磁盤緩存
- 內(nèi)存緩存:YYMeroryCache
適用于體積小,速度快。內(nèi)部實(shí)現(xiàn)了LRU(緩存淘汰算法),使用雙向鏈表來(lái)存儲(chǔ)。
LRU的實(shí)現(xiàn):淘汰訪問(wèn)頻率低的節(jié)點(diǎn),當(dāng)存入一個(gè)新節(jié)點(diǎn)就放置頭部,放存入一個(gè)已經(jīng)存在的節(jié)點(diǎn)就把當(dāng)前節(jié)點(diǎn)拿出來(lái)放置頭部。刪除的時(shí)候從鏈表尾端開(kāi)始刪除。
鏈表采用C語(yǔ)言的字典來(lái)實(shí)現(xiàn),節(jié)點(diǎn)內(nèi)部元素有parentNode、childNode,緩存開(kāi)銷等變量。采用pthread_mutex_lock鎖的機(jī)制來(lái)處理資源訪問(wèn)的時(shí)候線程安全。 - 磁盤緩存: YYDiskCache
適用于體積大,相對(duì)來(lái)說(shuō)速度慢。
使用YYKVStore來(lái)管理對(duì)文件的操作,磁盤緩存分2種,一種是數(shù)據(jù)庫(kù)存儲(chǔ),一種是數(shù)據(jù)庫(kù)/文件混合存儲(chǔ)
當(dāng)資源>20KB的時(shí)候會(huì)采用混合存儲(chǔ),此時(shí)數(shù)據(jù)的元數(shù)據(jù)存在sqlite3數(shù)據(jù)庫(kù)中,數(shù)據(jù)存在文件系統(tǒng)中去。采用信號(hào)量對(duì)資源進(jìn)行加鎖。
總結(jié):YYCache的設(shè)計(jì)流程:先內(nèi)存后磁盤,雙重實(shí)現(xiàn)來(lái)對(duì)數(shù)據(jù)的緩存,LRU算法,雙向鏈表的使用。
磁盤緩存使用數(shù)據(jù)庫(kù)跟文件混合存儲(chǔ),性能上極大的提升。
使用pthread_metux_lock和信號(hào)量分別的不同的方式進(jìn)行線程安全的維護(hù)。他們的區(qū)別在于信號(hào)量在等待的時(shí)候性能優(yōu)于pthread_metux_lock,等待的時(shí)候不消耗CPU。而且信號(hào)量在處理線程等待的時(shí)候會(huì)對(duì)線程進(jìn)行順序進(jìn)行,而pthread_metux_lock等待的時(shí)候是無(wú)序的。
Masorny
Masorny是一個(gè)可以對(duì)屏幕進(jìn)行適配一個(gè)輕量級(jí)的布局架構(gòu),他是封裝了系統(tǒng)的AutoLayout來(lái)實(shí)現(xiàn)的。內(nèi)部使用了鏈?zhǔn)骄幊痰娘L(fēng)格,點(diǎn)語(yǔ)法,可以循環(huán)式調(diào)用自身,增加了diamante的可讀性,優(yōu)化了代碼風(fēng)格。MASConstraintMaker是一個(gè)工廠類。
總結(jié):鏈?zhǔn)骄幊趟枷耄褂命c(diǎn)語(yǔ)法,隱式block回調(diào)。
WebViewJavaScriptBridge
WebViewJavaScriptBridge是H5跟OC交互的一個(gè)常用的庫(kù)。
- 初始化:在OC端初始化bridge,H5端寫入setupJavascript方法,創(chuàng)建一個(gè)iframe標(biāo)簽,設(shè)置scr為“https://bridge_loaded”,注入JS腳本,webview的代理方法webView:decidePolicyForNavgationAction:...方法可以檢測(cè)到。
- OC調(diào)用H5:調(diào)用callHandle方法,base調(diào)用sendData方法,封裝一個(gè)唯一的消息id,存在本地。接著調(diào)用,將消息json序列化,webview注入JS,執(zhí)行H5中對(duì)應(yīng)的handleName的方法回調(diào)。
3.H5調(diào)用OC:H5端調(diào)用callHandle,本地調(diào)用registerHandle,將handleName存入字典。H5調(diào)用callHandle,觸發(fā)注入的JS代碼中的callHandle方法,內(nèi)部調(diào)用__doSend方法,將iframe的scr重新改寫,這時(shí)webView的webview:decidePolicyForNavgationAction代理方法,根據(jù)handleName找到存儲(chǔ)在本地的messageQueue的block,執(zhí)行block,調(diào)用OC的方法。
總結(jié):OC通過(guò)webview執(zhí)行JS代碼,來(lái)通知H5,觸發(fā)回調(diào)。H5通過(guò)iframe標(biāo)簽設(shè)置scr,然后webView的decidePolicyForNavgationAction方法接收到響應(yīng),觸發(fā)回調(diào)方法。