成功登入後我們會需要 user 的 token 給儲存起來,可以做為下次登入的依據,不用在重複登入,也可以在之後使用,這時候我們就會需要用到像 iOS 裡的 UserDefaults ,或者是 Android 中的 SharedPreferences 來儲存資料,我們會需要先在原生的平台跟 flutter 之間定義一個介面來操作,還好有第三方套件實作了這些功能,那就是 shared_preference
。
添加套件到pubspec.yaml
中
dependencies:
shared_preferences: ^0.5.10
安裝
flutter pub get
import 到要使用的地方
import 'package:shared_preferences/shared_preferences.dart';
儲存前需要先取得 sharedPreferences 的 instance ,再利用 set 的方法來儲存,目前提供 bool ,int ,double ,string ,stringList的儲存方式。
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("key", value) ;
這裡可能有人會好奇為啥會需要使用 await 做非同步的的方式,因為我自己也很好奇所以去看了下 source code,裡面就有寫到,因為是去硬碟做讀寫,它不應該在表現力敏感的區域中等待,意思應該是硬碟的效能可能有好有壞也很敏感,我們有時候可能會需要等待它,所以才需要用 async 去等待回傳。
原文在這,如果我有理解錯誤請糾正我感謝
Because this is reading from disk, it shouldn't be awaited in performance-sensitive blocks.
對於每個 setter 都有對應的 getter 可以使用 , 例如 getBool , getInt , getString 等等
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String key = sharedPreferences.getString("key")
可能需要注意的地方是不管是什麼型別,如果 key 值取出來沒有東西就會是null
//不希望傳遞 null 的話可以給預設值
String key = sharedPreferences.getString("key") ?? "default" ;
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.remove("key");
使用 sharedPreferences 到後期時我們可能會遇到需要儲存的資料種類變多了,和在不同地方使用同一個資料,為了方便我們管理和使用,我們可以創造一個類別來管理它。
自行封裝的類別
//SharedPreferenceManager.dart
//先定義資料的種類
enum ValueType {
BOOL,
INT,
STRING,
DOUBLE,
STRING_LIST,
}
//我們需要的key
enum SharedPreferenceKey {
//有新的資料需要儲存需要來這裡新增
token
}
//透過 extension 去擴展 key
extension KeyExtension on SharedPreferenceKey{
//利用定義好的 key 去產生字串
String get key => this.toString();
//設定key 相對的type
ValueType get valueType {
switch(this){
//有新的資料需要儲存需要來這裡新增
case SharedPreferenceKey.token:
return ValueType.STRING ;
}
}
}
class SharedPreferenceManager {
static SharedPreferenceManager _sharedPreferenceManager ;
static SharedPreferences _sharedPreferences ;
static Future<SharedPreferenceManager> getInstance() async {
if (_sharedPreferences == null || _sharedPreferenceManager == null){
_sharedPreferences = await SharedPreferences.getInstance() ;
_sharedPreferenceManager = SharedPreferenceManager() ;
}
return _sharedPreferenceManager;
}
set(SharedPreferenceKey key ,dynamic value){
//利用 key 的 valueType 去判斷我們改寫入哪種資料
switch( key.valueType ){
case ValueType.BOOL:
_sharedPreferences.setBool(key.key, value);
break;
case ValueType.STRING:
_sharedPreferences.setString(key.key, value);
break;
case ValueType.STRING_LIST:
_sharedPreferences.setStringList(key.key, value);
break;
case ValueType.INT:
_sharedPreferences.setInt(key.key, value);
break;
case ValueType.DOUBLE:
_sharedPreferences.setDouble(key.key, value);
break;
}
}
dynamic get(SharedPreferenceKey key) => _sharedPreferences.get(key.key) ;
}
取得 instance 的地方我沿用跟本來一樣的方式去取得這個地方感可以再改寫,但是目前沒什麼想法,
然後現在的 set 已經不需要去管字串跟型別了,透過 enum 我們可以找到我們要set的key,value如果跟設定傳的不一樣就會報錯誤所以也不用擔心。
SharedPreferenceManager spm = await SharedPreferenceManager.getInstance() ;
spm.set(SharedPreferenceKey.token, "test");
get 賦值錯誤也會報錯
SharedPreferenceManager spm = await SharedPreferenceManager.getInstance() ;
String token = spm.get(SharedPreferenceKey.token) ;
希望有看到這邊的各位可以留下自己的想法,因為 dart 學習也沒有很久,肯定還有更好的方法,是我沒想到的,或是自己都用什麼方式來管理 SharedPreference 也可以在下面分享一下,大家互相分享交流,一起蓋個 SharedPreference 大樓吧~