Flutter classe utilie per shared preferences

Nell’articolo shared preferences in depth, ho spiegato come utilizzare la shared preferences in Flutter. In questo articolo voglio invece mostrarvi una classe che ho ideato per semplificare l’utilizzo. Ho creato questa classe per l’esigenza di dover memorizzare i dati degli utenti. Ad esempio l’ho usata in Send to Kindle per memorizzare una lista di mail. L’ho usata anche per memorizzare la lista dei token e dati d’acquisto dell’utente.

In generale questa struttura può essere utilizzata laddove serve lavorare con una lista di stringhe. Nell’articolo precedente, ho già mostrato come fare a memorizzare una lista di stringhe in local cache. Questa classe però rende l’utilizzo ancora più semplici e aggiunge dei metodi che ci permettono di lavorare in maniera più rapida.

Come prima cosa, ho creato il metodo per salvare una lista il local cache nel seguente modo:

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);
  }

Successivamente ho creato un altro metodo per recuperare la lista, inoltre ho messo qui i controlli del caso se empty o null:

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

Man mano che la usavo ho avuto la necessità di dover aggiungere altri metodi. Metodi per:

  • Cancellare la lista.

  • Inserire una stringa per volta.

  • Fare l’override della lista.

  • Verificare se un elemento esiste.

  • Prendere il primo elemento della lista.

  • Salvare un elemento in top alla lista.

In questo modo la classe alla fine è diventata così:

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);
  }
}

Facendo così ho semplificato molto e reso più semplice i punti di chiamata. Inoltre se dovesse cambiare il plugin shared preference utilizzato, c’è un unico posto dove dover intervenire.

Last modified: 1 June 2020