iOS離線快取架構設計方案
原文釋出在個人簡書,更多內容歡迎關注筆者簡書 ,評論、互相交流請到簡書,謝謝!
現在許多主流的App都會做離線快取
功能,比如“今日頭條”,“新浪微博”,每次啟動專案或者重新整理有網路時都是獲取網路資料,網路出錯時會展示快取資料提高使用者體驗。
筆者就結合之前見過的、以及筆者自己做快取的方式,談一談離線快取的實現方案以及其中的優缺點。“今日頭條”,“新浪微博”都是快取了第一頁的資料,筆者這裡也是這樣。
無demo不文章,筆者已將demo1 和demo2 寫好,歡迎下載.
快取資料的方式一般有以下幾種:
- 儲存到plist檔案
- 儲存到沙盒
- CoreData
- 資料庫
由於這裡快取相對大量的資料,採用sqllite資料庫來實現離線快取。
通過下面幾個問題來講述離線快取的過程
- 怎麼設計SQL語句?
- 快取什麼樣的資料到資料庫: JSON格式資料 or 模型格式資料?
- 快取key的格式:URL+引數的方式
- 快取的方案
一、怎麼設計SQL語句?
有的朋友在做快取的時候,會這樣設計sql語句
上面的方式設計sql語句,看上去明顯很繁瑣,涉及到的欄位很多也容易混亂。筆者不會採用這樣方式設計sql,而是像下面這種方式去設計sql
上面的sql語句很明顯避免了那麼多欄位的干擾。不論是以 JSON資料格式
還是模型資料格式
,筆者會將資料已二進位制的方式存入資料庫(BLOB是資料庫中用來儲存二進位制檔案的欄位型別
- cache_data 是快取的二進位制資料
- cache_key 是快取時唯一的key,通過唯一的key就可以獲取的對應的快取資料(後面還會對這個欄位進行詳細說明)
二、快取什麼樣的資料到資料庫: JSON格式資料 or 模型格式資料?
有人喜歡快取模型(model)->轉換成二進位制資料->存入資料庫
但是快取模型的過程需要模型實現NSCoding協議並進行coder和encoder
,如果採用了像YYModel或者MJExtension這樣的第三方庫,實現coder和encoder
還相對方便一些,但是如果是自己實現這個過程還是有些繁瑣的過程。
所以,筆者採用JSON格式資料->轉換成二進位制資料->快取資料庫
三、快取key的格式:URL+引數的方式
下面來說一下cache_key的格式,筆者這裡採用的是網路介面請求的url+請求引數
拼接組成一個完整的字串
來作為cache_key。
為什麼採用URL+引數
的方式作為cache_key那?
因為URL+引數
可以區分介面的唯一性,因為做網路請求時知道了url和請求引數就知道了要請求哪個介面。
筆者這裡只設計了T_CACHE
一張表,所有的資料快取都存放在這一張表裡,所以需要一個區分快取資料的唯一標識,通過這個唯一標識我們就知道要獲取的首頁資料的快取、還是其他什麼頁的快取。顯然URL+引數
作為這個唯一標識很合適,採用URL+引數
的方式通用性也很強,我們拿到其他專案也適用。因為不論什麼專案幾乎都是通過URL+引數
方式進行介面請求。
四、快取的方案
針對快取資料的設計方案,各位可以說是各顯神通。
有人會針對每一個要進行離線快取的介面設計一套sql語句和快取類進行資料的存取,也有人會像下面的設計方式進行資料存取。
筆者離線快取思路如下:
為什麼會採用上面的快取方案那?
因為我們在實際專案開發中,有時候在專案最開始我們並不是很清楚要不要做離線快取功能的。有時候情況會是這樣的,專案已經維護了幾個版本了,產品經理某一天突然告訴你XXX介面顯示不友好,加上離線快取功能吧;也有可能你之前的專案經過了好幾手,裡面有之前的開發人員設計的快取方案,而每種方案又都不一樣。這時採用筆者這種方案是在現有專案基礎上,以最小的改動實現離線快取的一種方式。當然,應該還會有更好的方式吧,如果大家有其他好的方式,非常非常歡迎指點交流。
下面對筆者的快取方案進行詳細講解
首先先說一下網路層的一個小設計點,有的人會像下面的設計方式進行網路層API的請求。
有一個APIRequest統一處理所有的網路請求,每個介面的資料通過block或者是delegate等方式返回去。如果是通過這種方案進行的網路請求,那麼就可以通過下面的方式進行離線快取。
說明:
這裡需要對isCache666
這個引數進行一下說明,因為我們並不需要對所有的介面請求做離線快取,可能是針對某些介面資料做快取,那此時我們就需要區分哪些介面要做快取、哪些不需要做快取。為了實現這個區分,我們手動的添加了一個isCache666
這樣一個引數,這裡為了直觀,就傳了一個YES,其實傳什麼資料都可以,因為在下面判斷的時候只是判斷cacheKey這個字串中是否包含isCache666
這樣的子字串(這裡為了防止和後臺返回的欄位衝突,所以命名一些不容易衝突的名字)
針對上面的這樣情況,筆者已經寫好了demo1,詳細的細節可以下載demo1看一下
筆者採用的網路API請求方案是這樣的,每一個API對應於一個XXXAPIRequest類,然後這個XXXAPIRequest提供請求的URL和引數、請求方式、該請求是否需要進行離線快取等資訊。
說明:
所有的 XXXAPIRequest類
需要遵守APIRequestProtocol協議
,並且必須實現apiRequestURL和apiRequestParams
方法,提供請求需要的url和引數; 預設是POST請求方式,可以重寫method方法來修改請求方式,同樣預設isCache為NO(不進行離線快取),如果要設定離線快取,重寫isCache方法,返回YES即可。
針對上述的快取方案,筆者已經寫好了demo2,詳細的細節可以下載demo2看一下
最後
上面說的離線快取方案是筆者個人的一些觀點,當然離線快取方案還有其他的方式,也歡迎大家交流。筆者這裡也是拋磚引玉,好的方案歡迎拍過來。