Flutter shared_preferences 探究

碼個蛋同學發表於2019-05-30

起因

Flutter 中使用三方外掛的時候,很好奇,他是怎麼做到,跨平臺,既能在iOS上使用,也能在Android上使用?

一探究竟

拿常用的資料持久化的 shared_preferences 來看,他的功能在iOS上和 NSUserDefaults 的功能基本類似, 在安卓上 基本上和 SharedPreferences 一樣,

猜想

  1. 用Flutter 自己的某種方法實現,和Flutter 的介面一樣,既不是在iOS中轉化成了 UIViewController 也不是在Android中轉化成了 Activity,
  2. 和RN一樣,在iOS上呼叫了iOS的實現,在安卓上呼叫了安卓的實現,

結果

最後看了 shared_preferences 的原始碼,發現,shared_preferences 是基於通道, 在iOS上 和 android 有不同的實現,和猜想二一樣,在 iOS 上使用了 NSUserDefaults 安卓使用了 SharedPreferences

iOS的實現

通道, 以庫的名稱為通道名,註冊了一個 FlutterMethodChannel

FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:CHANNEL_NAME
                                                              binaryMessenger:registrar.messenger];
複製程式碼

在iOS 中 通過通道的 result 將結果返回,這裡摘出一小部分,就可以理解,這裡 摘出的是 shared_preferencessetBool 的實現,對映的是iOS 中的

 [[NSUserDefaults standardUserDefaults] setBool:value.boolValue forKey:key];
複製程式碼

摘出的部分如下:

 else if ([method isEqualToString:@"setBool"]) {
      NSString *key = arguments[@"key"];
      NSNumber *value = arguments[@"value"];
      [[NSUserDefaults standardUserDefaults] setBool:value.boolValue forKey:key];
      result(@YES);
    } else if ([method isEqualToString:@"setInt"]) {
      NSString *key = arguments[@"key"];
      NSNumber *value = arguments[@"value"];
     
      [[NSUserDefaults standardUserDefaults] setValue:value forKey:key];
      result(@YES);
複製程式碼

android的實現

android 和 iOS 的實現基本類似, 首先也是註冊通道,然後 對映到安卓的 SharedPreferences 來實現

通道- 主要程式碼

 MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME);
    SharedPreferencesPlugin instance = new SharedPreferencesPlugin(registrar.context());
    channel.setMethodCallHandler(instance);
複製程式碼

對應的實現 這裡也摘出 部分, Flutter 中的 shared_preferences 的setBool 對應 android 的

status = preferences.edit().putBoolean(key, (boolean) call.argument("value")).commit();
複製程式碼

摘出的內容如下

switch (call.method) {
        case "setBool":
          status = preferences.edit().putBoolean(key, (boolean) call.argument("value")).commit();
          break;
        case "setDouble":
          double doubleValue = ((Number) call.argument("value")).doubleValue();
          String doubleValueStr = Double.toString(doubleValue);
          status = preferences.edit().putString(key, DOUBLE_PREFIX + doubleValueStr).commit();
          break;
複製程式碼

相關文章