天天看點

IOS應用架構思考二(網絡圖檔庫)

移動端架構中圖檔庫是非常重要的一環,其實圖檔庫也可以了解為網絡庫的一種特殊使用模式,為了滿足需要,圖檔庫至少要滿足以下特點:

提供一個加載入口,通常以uiimageview的類别方法<code>setimagewithurl:...</code>開始

支援異步網絡加載圖檔

支援記憶體緩存和檔案緩存

確定同一張圖檔不會被重複下載下傳

主流圖檔格式的解碼

著名的優秀關于圖檔加載的庫有:

<a href="https://github.com/rs/sdwebimage">sdwebimage</a>

<a href="https://github.com/afnetworking/afnetworking">afnetworking</a>

首先你要設計一個全局的隊列來執行下載下傳任務,因為我們要保證下載下傳任務不重複,那麼就需要一個任務管理器來統一排程下載下傳任務,比如有2個uiimageview同時加載同一張圖檔,那麼就隻執行一次下載下傳,下載下傳完成回調給2個view就行了。

回調的方式 <code>sdwebimage</code> 采用<code>block</code>的方式,<code>egoimageloading</code>采用了<code>notification</code>的方式, 因為可能存在多個回調, 是以不太适合用delegate的方式進行回調,不過如果非要想用也可以,可以建立一個weak引用的<code>cfarrayref</code> 或者用 <code>nshashtable</code> 來把儲存 delegate 指針。

說到緩存,我們知道在ios5之後,nsurlcache 也有diskcache了,是不是我們不需要自己實作cache機制了,直接使用nsurlcache就好了呢? 分析這個必要性,我們首先要思考nsurlcache中儲存的是什麼,nsurlcache中儲存的是http協定傳回的rawdata, 沒有經過解壓和解碼的過程, 如果直接使用nsurlcache, 那麼每次讀緩存的時候就還需要把rawdata解碼為我們需要的uiimage,這肯定會帶來額外的cpu開銷。那如果我們 自己來做緩存,我們可以将解碼後的資料儲存到disk,就可以減少我們讀緩存的時間了。這一點也是我覺得sdwebimage唯一比afnetworking好 的一個亮點了,其他的afnetworking也都做到了,(afnetworking直接使用nsurlcache做diskcache, 在背景線程解碼image)

關于緩存,我們還需要設計記憶體緩存,diskcache 在讀取的時候還是要消耗i/o的時間,可能帶來對fps的影響和電量的消耗, 那麼我們設計記憶體緩存在一定程度上可以緩解這個問題,對于頻繁使用的圖檔,效果會更好。ps: 記憶體緩存需要做好記憶體控制,不能讓其過多 的占用記憶體,比如記憶體警告時要清空。 nsurlcache 雖然也有記憶體緩存,但是不太可控,是以記憶體緩存還是自己實作比較合适。

緩存時間的設定其實比較重要,其實有時候緩存時間的設定,使用nsurlcache的話,緩存時間可以是由圖檔伺服器來決定的,用戶端不用太操心什麼, 這個是用nsurlcache的好處,那麼如果我們自己實作的緩存方式呢,sdwebimage裡面是可以統一設定緩存的時間,預設是一周的時間,其實這個設定 我是覺得不太合理的,因為不同的業務場景很可能會要求不同的緩存時間設定,怎麼能夠大一統的設定了事,不過好在現在的一般應用場景沒有對緩存 時間硬性的要求,是以用起來也沒什麼問題。

話說我以前在蘇甯易購的時候,就對egoimageloading做過大修改,添加了很多sdwebimage的優點特性,關于緩存時間也做了個性化設定。但其實nsurlcache 的方式才是決定緩存壽命的最好的方式。

有時候可能會有一些圖檔裁剪的需求,比如說placeholder随着view大小自适應,或者一張源圖檔可能會裁剪為不同尺寸來展示,那麼這個時候可能會做一些裁剪的 操作,裁剪操作可能需要做到2點,不要在主線程做,不要重複裁剪相同尺寸。

暫時也寫到這吧,以後有補充再寫,歡迎勘誤。