Flutter useful class for shared preferences

In the article shared preferences in depth, I explained how to use shared preferences in Flutter. In this article I want to show you a class that I designed to simplify its use. I created this class out of the need to store user data. For example, I used it in Send to Kindle to store a mail list. I also used it to store the user’s token list and to purchase data.

Overall, this structure can be used where there is the need of working with a list of strings. In my previous article, I have already shown how to store a list of strings in local cache. This class, however, makes it even easier to use and adds methods that allow us to work faster.

First, I created the method to save a local cache list as follows:

class CashedUserData {
  static Future<void> _writes = Future.value();
//add list by key reference in local cache  
static Future<void> addlist(String kPrefKey, List<String> stringList) async{
    _writes = _writes.then((void _) => _doAddList(kPrefKey,stringList));
    return _writes;
  }
}
static Future<void> _doAddList(String kPrefKey, List<String> list) async {
    List<String> cached = await load(kPrefKey);
    cached.addAll(list);
    await (await SharedPreferences.getInstance()).setStringList(kPrefKey, cached);
  }

Then I created another method to retrieve the list, I have also put the appropriate checks here, if empty or null:

 static Future<List<String>> load(String kPrefKey) async {
    return (await SharedPreferences.getInstance()).getStringList(kPrefKey) ??
        [];
  }

As I used it, I needed to add more methods. Methods to:

  • Clear the list.

  • Enter one string at a time

  • Override the list

  • Check if an element exists

  • Take the first item on the list.

  • Save an item at the top of the list.

In this way the class eventually became like this:

class CashedUserData {
  static Future<void> _writes = Future.value();
  static Future<void> overrideListData(String kPrefKey, List<String> stringList) async{
    _writes = _writes.then((void _) => _doOverrideListData(kPrefKey,stringList));
    return _writes;
  }
  static Future<void> addlist(String kPrefKey, List<String> stringList) async{
    _writes = _writes.then((void _) => _doAddList(kPrefKey,stringList));
    return _writes;
  }
  static Future<void> save(String kPrefKey, String id) async{
    if(await CashedUserData.exist(kPrefKey, id))
      return;
    _writes = _writes.then((void _) => _doSave(kPrefKey,id));
    return _writes;
  }
  static Future<void> saveAsFirst(String kPrefKey, String id) async{
    List<String> actuaList = await load(kPrefKey);
    if(actuaList!=null &&  actuaList.length == 0 )
      return save(kPrefKey,id);
    if(actuaList.contains(id))
      actuaList.remove(id);
    
    if(actuaList.length>1)
      actuaList.removeAt(0);
    List<String> newlist = new List();
    newlist.add(id);
    newlist.addAll(actuaList);
    _writes = _writes.then((void _) => _doOverrideListData(kPrefKey,newlist));
    return _writes;
  }
  static Future<void> delete(String kPrefKey, String id) {
    _writes = _writes.then((void _) => _doDelete(kPrefKey,id));
    return _writes;
  }
  static Future<String> getFirst(String kPrefKey) async {
    List<String> dataList = (await SharedPreferences.getInstance()).getStringList(kPrefKey);
    return (dataList!=null && dataList.length>0) ? dataList[0] : "";
  }
  static Future<List<String>> load(String kPrefKey) async {
    return (await SharedPreferences.getInstance()).getStringList(kPrefKey) ??
        [];
  }
  static Future<bool> exist(String kPrefKey, String id) async {
    List<String> userDataList = (await SharedPreferences.getInstance()).getStringList(kPrefKey) ?? [];
    return (userDataList!=null &&  userDataList.length > 0) ? userDataList.contains(id) : false;
  }
  static Future<void> _doSave(String kPrefKey, String id) async {
    List<String> cached = await load(kPrefKey);
    cached.add(id);
    await (await SharedPreferences.getInstance()).setStringList(kPrefKey, cached);
  }
  static Future<void> _doDelete(String kPrefKey, String id) async {
    List<String> cached = await load(kPrefKey);
    cached.remove(id);
    await (await SharedPreferences.getInstance()).setStringList(kPrefKey, cached);
  }
 static Future<void> _doAddList(String kPrefKey, List<String> list) async {
    List<String> cached = await load(kPrefKey);
    cached.addAll(list);
    await (await SharedPreferences.getInstance()).setStringList(kPrefKey, cached);
  }
 static Future<void> _doOverrideListData(String kPrefKey, List<String> list) async {
    await (await SharedPreferences.getInstance()).setStringList(kPrefKey, list);
 }
  static update(String kPrefKey, String currentItem, String kindlemail) async{
    List<String> actuaList = await load(kPrefKey);
    if(actuaList!=null &&  actuaList.length > 0  )
    {
     try{actuaList[actuaList.indexOf(currentItem)] = kindlemail;} catch (e) {}
    }
    await overrideListData(kPrefKey, actuaList);
  }
}

By doing this I simplified the call points. Furthermore, if the plugin shared preference used changed, there would only be one place where to take action.

Last modified: 1 June 2020