Flutter之shared_preferences的使用、源碼分析(二)

shared_preferences源碼分析

實(shí)例化對(duì)象源碼分析
接下來我們來對(duì)shared_preferences進(jìn)行分析,我們?cè)谑褂玫臅r(shí)候需要通過getInstance實(shí)例化一個(gè)對(duì)象,接下來我們看下這里面它都做了什么操作泪喊。

靜態(tài)變量分析
我們先來看下它定義了三個(gè)靜態(tài)變量:

_prefix: 設(shè)置持久化數(shù)據(jù)和讀取持久化數(shù)據(jù)時(shí)統(tǒng)一設(shè)置前綴(flutter.)
_completer: 持久化數(shù)據(jù)異步通知,就是當(dāng)shared_preferences實(shí)例化完成后通過completer.future來返回結(jié)果
_manualDartRegistrationNeeded: 是否需要手動(dòng)注冊(cè)髓涯,因?yàn)樯婕暗?code>Linux袒啼、WindowsMac Os的持久化數(shù)據(jù)時(shí)纬纪,是需要手動(dòng)進(jìn)行注冊(cè)的蚓再,默認(rèn)為true

static const String _prefix = 'flutter.';
static Completer<SharedPreferences>? _completer;
static bool _manualDartRegistrationNeeded = true;

getInstance()源碼分析

當(dāng)我們獲取實(shí)例化對(duì)象時(shí)先判斷_completer是否為空,如果不為空則直接返回它的的future結(jié)果包各,否則它會(huì)實(shí)例化一個(gè)SharedPreferencesCompleter對(duì)象摘仅,然后通過_getSharedPreferencesMap來獲取持久化的map對(duì)象,獲取到map對(duì)象后问畅,通過completer.complete(SharedPreferences._(preferencesMap))Map結(jié)果返回出去娃属,代碼如下:

static Future<SharedPreferences> getInstance() async {
  if (_completer == null) {
    final completer = Completer<SharedPreferences>();
    try {
      final Map<String, Object> preferencesMap =
        await _getSharedPreferencesMap();
      completer.complete(SharedPreferences._(preferencesMap));
    } on Exception catch (e) {
      // If there's an error, explicitly return the future with an error.
      // then set the completer to null so we can retry.
      completer.completeError(e);
      final Future<SharedPreferences> sharedPrefsFuture = completer.future;
      _completer = null;
      return sharedPrefsFuture;
    }
    _completer = completer;
  }
  return _completer!.future;
}

_getSharedPreferencesMap()源碼分析

在我們調(diào)用getInstance()方法里,會(huì)調(diào)用_getSharedPreferencesMap()來獲取持久化的Map數(shù)據(jù)护姆,我們接下來看看它是如何獲取的矾端,首先它通過_store.getAll()就可以直接獲取到本地的所有持久化數(shù)據(jù),當(dāng)我們調(diào)用_store時(shí)卵皂,它會(huì)判斷是否需要手動(dòng)注冊(cè)

不需要手動(dòng)注冊(cè)時(shí):
iOS秩铆、Android等平臺(tái)中使用不需要手動(dòng)注冊(cè),所以它直接就返回的對(duì)應(yīng)的實(shí)例對(duì)象

需要手動(dòng)注冊(cè)時(shí):
先判斷是否是web灯变,如果是就返回localStorage殴玛,否則判斷是Linux還是Windows,然后根據(jù)平臺(tái)的不同返回其對(duì)應(yīng)的實(shí)例柒凉。

static Future<Map<String, Object>> _getSharedPreferencesMap() async {
  final Map<String, Object> fromSystem = await _store.getAll();
  assert(fromSystem != null);
  // Strip the flutter. prefix from the returned preferences.
  final Map<String, Object> preferencesMap = <String, Object>{};
  for (String key in fromSystem.keys) {
    assert(key.startsWith(_prefix));
    preferencesMap[key.substring(_prefix.length)] = fromSystem[key]!;
  }
  return preferencesMap;
}

static SharedPreferencesStorePlatform get _store {
  // TODO(egarciad): Remove once auto registration lands on Flutter stable.
  // https://github.com/flutter/flutter/issues/81421.
  if (_manualDartRegistrationNeeded) {
    // Only do the initial registration if it hasn't already been overridden
    // with a non-default instance.
    if (!kIsWeb &&
        SharedPreferencesStorePlatform.instance
        is MethodChannelSharedPreferencesStore) {
      if (Platform.isLinux) {
        SharedPreferencesStorePlatform.instance = SharedPreferencesLinux();
      } else if (Platform.isWindows) {
        SharedPreferencesStorePlatform.instance = SharedPreferencesWindows();
      }
    }
    _manualDartRegistrationNeeded = false;
  }

  return SharedPreferencesStorePlatform.instance;
}

_setValue()源碼分析

不管我們是存儲(chǔ)什么內(nèi)容的數(shù)據(jù),最終都會(huì)調(diào)用_setValue()來進(jìn)行存儲(chǔ)扰楼,

首先它會(huì)檢查存入的value是否為空之碗,如果為空就拋出異常架忌,否則就用_prefix + key來作為存入的key值臭杰。

判斷存入的值是不是List<String>,如果是先把value通過toList()方法轉(zhuǎn)換蔬咬,然后在存入鲤遥,否則直接存入,這步存入操作只是存入緩存中林艘,當(dāng)應(yīng)用程序退出時(shí)將消失
最后通過_store來異步寫入到磁盤中

Future<bool> _setValue(String valueType, String key, Object value) {
  ArgumentError.checkNotNull(value, 'value');
  final String prefixedKey = '$_prefix$key';
  if (value is List<String>) {
    // Make a copy of the list so that later mutations won't propagate
    _preferenceCache[key] = value.toList();
  } else {
    _preferenceCache[key] = value;
  }
  return _store.setValue(valueType, prefixedKey, value);
}

本篇主要講了shared_preferences的源碼盖奈,下篇講講項(xiàng)目中使用shared_preferences的封裝部分。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狐援,一起剝皮案震驚了整個(gè)濱河市钢坦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啥酱,老刑警劉巖爹凹,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異镶殷,居然都是意外死亡禾酱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門绘趋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颤陶,“玉大人,你說我怎么就攤上這事陷遮∽易撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵拷呆,是天一觀的道長(zhǎng)闲坎。 經(jīng)常有香客問我,道長(zhǎng)茬斧,這世上最難降的妖魔是什么腰懂? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮项秉,結(jié)果婚禮上绣溜,老公的妹妹穿的比我還像新娘。我一直安慰自己娄蔼,他們只是感情好怖喻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岁诉,像睡著了一般锚沸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涕癣,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天哗蜈,我揣著相機(jī)與錄音,去河邊找鬼。 笑死距潘,一個(gè)胖子當(dāng)著我的面吹牛炼列,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播音比,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼俭尖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了洞翩?” 一聲冷哼從身側(cè)響起稽犁,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎菱农,沒想到半個(gè)月后缭付,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡循未,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年陷猫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片的妖。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绣檬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嫂粟,到底是詐尸還是另有隱情娇未,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布星虹,位于F島的核電站零抬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宽涌。R本人自食惡果不足惜平夜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卸亮。 院中可真熱鬧忽妒,春花似錦、人聲如沸兼贸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)溶诞。三九已至鸯檬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間螺垢,已是汗流浹背喧务。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工颜及, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹂楣。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像讯蒲,于是被迫代替她去往敵國(guó)和親痊土。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容