起因
在 Flutter
中使用三方外掛的時候,很好奇,他是怎麼做到,跨平臺,既能在iOS上使用,也能在Android上使用?
一探究竟
拿常用的資料持久化的 shared_preferences
來看,他的功能在iOS上和 NSUserDefaults
的功能基本類似, 在安卓上 基本上和 SharedPreferences
一樣,
猜想
- 用Flutter 自己的某種方法實現,和Flutter 的介面一樣,既不是在iOS中轉化成了
UIViewController
也不是在Android中轉化成了Activity
, - 和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_preferences
中 setBool
的實現,對映的是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;
複製程式碼