weex的數(shù)據(jù)緩存模塊之storage實(shí)現(xiàn)源碼閱讀

本文假設(shè)你對(duì)weex有基本的了解!(本文的目的是講解iOS的一種緩存方案實(shí)現(xiàn)螃成,weex的部分不懂并無(wú)大礙。如果不關(guān)心,可以直接從iOS實(shí)現(xiàn)的部分開始閱讀)

weex Module的簡(jiǎn)單介紹

言歸正題脓诡,先從官方文檔了解Storage的使用方式。
我們發(fā)現(xiàn)媒役,客戶端主要提供了4個(gè)API:

  • setItem(key, value, callback)
  • getItem(key, callback)
  • removeItem(key, callback)
  • length(callback)

下面祝谚,我們逐一分析他們的具體實(shí)現(xiàn)。

Storage 實(shí)現(xiàn)

1. 存儲(chǔ)數(shù)據(jù)

先上代碼:

- (void)setObject:(NSString *)obj forKey:(NSString *)key persistent:(BOOL)persistent callback:(WXModuleCallback)callback {
    NSString *filePath = [WXStorageModule filePathForKey:key];
    if (obj.length <= WXStorageLineLimit) {
        if ([WXStorageNullValue isEqualToString:self.memory[key]]) {
            [[WXUtility globalCache] removeObjectForKey:key];
            [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
        }
        self.memory[key] = obj;
        NSDictionary *dict = [self.memory copy];
        [self write:dict toFilePath:[WXStorageModule filePath]];
        [self setInfo:@{@"persistent":@(persistent),@"size":@(obj.length)} ForKey:key];
        [self updateIndexForKey:key];
        [self checkStorageLimit];
        if (callback) {
            callback(@{@"result":@"success"});
        }
        return;
    }
    
    [[WXUtility globalCache] setObject:obj forKey:key cost:obj.length];
    
    if (![WXStorageNullValue isEqualToString:self.memory[key]]) {
        self.memory[key] = WXStorageNullValue;
        NSDictionary *dict = [self.memory copy];
        [self write:dict toFilePath:[WXStorageModule filePath]];
    }
    
    dispatch_async([WXStorageModule storageQueue], ^{
        [obj writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
    });
    
    [self setInfo:@{@"persistent":@(persistent),@"size":@(obj.length)} ForKey:key];
    [self updateIndexForKey:key];
    
    [self checkStorageLimit];
    if (callback) {
        callback(@{@"result":@"success"});
    }
}

代碼解析:

  • 首先酣衷,在這個(gè)方法之前踊跟,檢驗(yàn)了key的類型。只能是NSString或NSNumber鸥诽,且不能為空商玫,并去除了空格和回車字符。
  • 其次牡借,根據(jù)key的name在沙盒的~/Document目錄下生成一個(gè)wxStorage目錄拳昌。文件名是name的MD5值。wxStorage目錄下存放數(shù)據(jù)內(nèi)容時(shí)會(huì)生成3個(gè)文件钠龙,分別是:wxStorage.plist炬藤,wxStorage.info.plistwxStorage.index.plist碴里。第一個(gè)存放數(shù)據(jù)鍵值對(duì)沈矿;第二個(gè)存放數(shù)據(jù)的額外信息,如存放時(shí)間咬腋、數(shù)據(jù)長(zhǎng)度羹膳、索引信息等;第三個(gè)存放key值根竿,用于遍歷陵像。
  • 如果data的內(nèi)容length小于Limit(weex指定為1024byte),則將該key/value直接寫入memory字典寇壳。memory是weex自身實(shí)現(xiàn)的一個(gè)線程安全型的字典醒颖。隨后,方法會(huì)依次把數(shù)據(jù)寫入上一步所說(shuō)的3個(gè)plist文件中壳炎。檢查storage是否超出Limit限制泞歉。如果是,則刪除部分內(nèi)容。
  • 如果data的內(nèi)容length大于Limit腰耙,先將該key/value存放于globalCache中偿洁。這是一個(gè)基于NSCache實(shí)現(xiàn)的全局緩存,目的是為了數(shù)據(jù)能在內(nèi)存中存儲(chǔ)沟优,被高效地使用涕滋。存儲(chǔ)的步驟和上面的“小數(shù)據(jù)”一樣。不同的是挠阁,大數(shù)據(jù)不是直接存放在plist中宾肺。plist中存放了一個(gè)假數(shù)據(jù),并和之前一樣同步的被寫入plist文件侵俗。而真數(shù)據(jù)是額外開了一個(gè)隊(duì)列锨用,異步寫入的。filePath即是當(dāng)前目錄隘谣,文件名為key的MD5值增拥。

總結(jié)一下:數(shù)據(jù)先是存放在了一個(gè)線程安全的字典中;以1024byte為分界線寻歧,如果是“小數(shù)據(jù)”掌栅,則同步寫入一個(gè)管理文件;如果是“大數(shù)據(jù)”码泛,則異步寫入文件猾封,每個(gè)數(shù)據(jù)單獨(dú)存放為一個(gè)文件。

2. 獲取數(shù)據(jù)

- (void)getItem:(NSString *)key callback:(WXModuleCallback)callback
{
    if ([self checkInput:key]) {
        if (callback) {
            callback(@{@"result":@"failed",@"data":@"key must a string or number!"}); // forgive my english
        }
        return;
    }
    
    if ([key isKindOfClass:[NSNumber class]]) {
        key = [((NSNumber *)key) stringValue]; // oh no!
    }
    
    if ([WXUtility isBlankString:key]) {
        if (callback) {
            callback(@{@"result":@"failed",@"data":@"invalid_param"});
        }
        return ;
    }
    
    NSString *value = [self.memory objectForKey:key];
    if ([WXStorageNullValue isEqualToString:value]) {
        value = [[WXUtility globalCache] objectForKey:key];
        if (!value) {
            NSString *filePath = [WXStorageModule filePathForKey:key];
            NSString *contents = [WXUtility stringWithContentsOfFile:filePath];
            if (contents) {
                [[WXUtility globalCache] setObject:contents forKey:key cost:contents.length];
                value = contents;
            }
        }
    }
    if (!value) {
        [self executeRemoveItem:key];
        if (callback) {
            callback(@{@"result":@"failed",@"data":@"undefined"});
        }
        return;
    }
    [self updateTimestampForKey:key];
    [self updateIndexForKey:key];
    if (callback) {
        callback(@{@"result":@"success",@"data":value});
    }
}

了解了如何存儲(chǔ)噪珊,獲取就相對(duì)簡(jiǎn)單了晌缘。依次,先從memory字典中找痢站,然后去globalCache中找磷箕,最后去filePath下找;如果都沒(méi)找到阵难,則移除該key岳枷,并把文件中和該key相關(guān)的內(nèi)容都刪除了。

總結(jié)

對(duì)比YYCache的實(shí)現(xiàn)多望,weex的storage模塊實(shí)現(xiàn)比較簡(jiǎn)單嫩舟,條理清晰氢烘。在簡(jiǎn)單的數(shù)據(jù)緩存上完全夠用了怀偷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市播玖,隨后出現(xiàn)的幾起案子椎工,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件维蒙,死亡現(xiàn)場(chǎng)離奇詭異掰吕,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)颅痊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門殖熟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人斑响,你說(shuō)我怎么就攤上這事菱属。” “怎么了舰罚?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵纽门,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我营罢,道長(zhǎng)赏陵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任饲漾,我火速辦了婚禮蝙搔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘考传。我一直安慰自己杂瘸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布伙菊。 她就那樣靜靜地躺著败玉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪镜硕。 梳的紋絲不亂的頭發(fā)上运翼,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音兴枯,去河邊找鬼血淌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛财剖,可吹牛的內(nèi)容都是我干的悠夯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼躺坟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沦补!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起咪橙,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤夕膀,失蹤者是張志新(化名)和其女友劉穎虚倒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體产舞,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡魂奥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了易猫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耻煤。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖准颓,靈堂內(nèi)的尸體忽然破棺而出违霞,到底是詐尸還是另有隱情,我是刑警寧澤瞬场,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布买鸽,位于F島的核電站,受9級(jí)特大地震影響贯被,放射性物質(zhì)發(fā)生泄漏眼五。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一彤灶、第九天 我趴在偏房一處隱蔽的房頂上張望看幼。 院中可真熱鬧,春花似錦幌陕、人聲如沸诵姜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棚唆。三九已至,卻和暖如春心例,著一層夾襖步出監(jiān)牢的瞬間宵凌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工止后, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞎惫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓译株,卻偏偏與公主長(zhǎng)得像瓜喇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子歉糜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355