iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
1
Mobile Development

Flutter App 開發實戰系列 第 6

Flutter 儲存資料 shared_preference [DAY 6]

成功登入後我們會需要 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 大樓吧~


上一篇
Flutter 頁面轉跳 Navigator / Route [DAY 5]
下一篇
用 Drawer 做個導覽頁面  [DAY 7]
系列文
Flutter App 開發實戰30

尚未有邦友留言

立即登入留言