web-dev-qa-db-fra.com

Comment puis-je stocker un tableau entier dans SharedPreferences?

Je souhaite sauvegarder/rappeler un tableau d'entiers à l'aide de SharedPreferences, est-ce possible?

18
user878813

Vous pouvez essayer de le faire de cette façon:

  • Placez vos entiers dans une chaîne, en délimitant chaque entier par un caractère, par exemple une virgule, puis enregistrez-les sous la forme d'une chaîne:

    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    int[] list = new int[10];
    StringBuilder str = new StringBuilder();
    for (int i = 0; i < list.length; i++) {
        str.append(list[i]).append(",");
    }
    prefs.edit().putString("string", str.toString());
    
  • Récupérez la chaîne et analysez-la à l'aide de StringTokenizer:

    String savedString = prefs.getString("string", "");
    StringTokenizer st = new StringTokenizer(savedString, ",");
    int[] savedList = new int[10];
    for (int i = 0; i < 10; i++) {
        savedList[i] = Integer.parseInt(st.nextToken());
    }
    
47
Egor

Vous ne pouvez pas mettre de tableaux dans SharedPreferences, mais vous pouvez contourner ce problème:

private static final String LEN_PREFIX = "Count_";
private static final String VAL_PREFIX = "IntValue_";
public void storeIntArray(String name, int[] array){
    SharedPreferences.Editor edit= mContext.getSharedPreferences("NAME", Context.MODE_PRIVATE).edit();
    edit.putInt(LEN_PREFIX + name, array.length);
    int count = 0;
    for (int i: array){
        edit.putInt(VAL_PREFIX + name + count++, i);
    }
    edit.commit();
}
public int[] getFromPrefs(String name){
    int[] ret;
    SharedPreferences prefs = mContext.getSharedPreferences("NAME", Context.MODE_PRIVATE);
    int count = prefs.getInt(LEN_PREFIX + name, 0);
    ret = new int[count];
    for (int i = 0; i < count; i++){
        ret[i] = prefs.getInt(VAL_PREFIX+ name + i, i);
    }
    return ret;
}
14
Rafael T

Voici ma version, basée sur la réponse d'Egor. Je préfère ne pas utiliser StringBuilder sauf si je construis une énorme chaîne, mais merci à Egor d'avoir utilisé StringTokenizer - je ne l'ai pas beaucoup utilisé dans le passé, mais c'est très pratique! FYI, cela est allé dans ma classe utilitaire:

public static void saveIntListPrefs(
    String name, Activity activity, List<Integer> list)
{
  String s = "";
  for (Integer i : list) {
    s += i + ",";
  }

  Editor editor = activity.getPreferences(Context.MODE_PRIVATE).edit();
  editor.putString(name, s);
  editor.commit();
}

public static ArrayList<Integer> readIntArrayPrefs(String name, Activity activity)
{
  SharedPreferences prefs = activity.getPreferences(Context.MODE_PRIVATE);
  String s = prefs.getString(name, "");
  StringTokenizer st = new StringTokenizer(s, ",");
  ArrayList<Integer> result = new ArrayList<Integer>();
  while (st.hasMoreTokens()) {
    result.add(Integer.parseInt(st.nextToken()));
  }
  return result;
}
5
Nick Bolton

Deux solutions:

(1) Utilisez http://commons.Apache.org/proper/commons-lang/apidocs/org/Apache/commons/lang3/StringUtils.html

Il a des fonctions de scission/jointure qui vous permettent de joindre et diviser les entiers dans une ligne:

StringUtils.join([1, 2, 3], ';')  = "1;2;3"
StringUtils.split("1;2;3", ';')   = ["1", "2", "3"]

Cependant, vous devrez toujours reconvertir les chaînes en entiers.

En fait, pour le fractionnement, Java.lang.String.split() fonctionnera aussi bien: http://docs.Oracle.com/javase/7/docs/api/Java/lang/String.html#split(Java.lang.String)

(2) Utilisez le SharedPreferences.putStringSet () (API 11):

    SharedPreferences.Editor editor = preferences.edit();
    int count = this.intSet.size();
    if (count > 0) {
        Set<String> theSet = new HashSet<String>();
        for (Long l : this.intSet) {
            theSet.add(String.valueOf(l));
        }
        editor.putStringSet(PREFS_KEY, theSet);
    } else {
        editor.remove(PREFS_KEY);
    }
    editor.commit();

Et pour le récupérer:

    Set<String> theSet = this.preferences.getStringSet(PREFS_KEY, null);
    if (theSet != null && !theSet.isEmpty()) {
        this.intSet.clear();
        for (String s : theSet) {
            this.intSet.add(Integer.valueOf(s));
        }
    }

Ce code n'intercepte pas les NPE ni les NumberFormatExceptions car l'intSet est par ailleurs assuré de ne contenir aucune valeur NULL. Mais bien sûr, si vous ne pouvez pas vous assurer que, dans votre code, vous devriez entourer ceci d'un try/catch.

4
Risadinha

J'aime utiliser JSON, qui peut être stocké et récupéré sous forme de chaîne, pour représenter des données complexes dans SharedPreferences. Donc, dans le cas d'un tableau int:

public void setPrefIntArray(String tag, int[] value)
{
    SharedPreferences.Editor prefEditor = PreferenceManager.getDefaultSharedPreferences(context)
            .edit();

    String s;
    try
    {
        JSONArray jsonArr = new JSONArray();
        for (int i : value)
            jsonArr.put(i);

        JSONObject json = new JSONObject();
        json.put(tag, jsonArr);

        s = json.toString();
    }
    catch(JSONException excp)
    {
        s = "";
    }

    prefEditor.putString(tag, s);
    prefEditor.commit();
}

public int[] getPrefIntArray(String tag, int[] defaultValue)
{
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);

    String s = pref.getString(tag, "");

    try
    {
        JSONObject json = new JSONObject(new JSONTokener(s));
        JSONArray jsonArr = json.getJSONArray(tag);

        int[] result = new int[jsonArr.length()];

        for (int i = 0; i < jsonArr.length(); i++)
            result[i] = jsonArr.getInt(i);

        return result;
    }
    catch(JSONException excp)
    {
        return defaultValue;
    }
}

La beauté est que la même idée peut être appliquée à toute autre donnée complexe pouvant être représentée en tant que JSON.

2
GozzoMan

Voici à quoi pourrait ressembler la solution "convertir en chaîne séparée par des virgules" dans Kotlin, implémentée en tant que fonctions d'extension:

fun SharedPreferences.Editor.putIntArray(key: String, value: IntArray): SharedPreferences.Editor {
    return putString(key, value.joinToString(
            separator = ",", 
            transform = { it.toString() }))
}

fun SharedPreferences.getIntArray(key: String): IntArray {
    with(getString(key, "")) {
        with(if(isNotEmpty()) split(',') else return intArrayOf()) {
            return IntArray(count(), { this[it].toInt() })
        }
    }
}

De cette façon, vous pouvez utiliser putIntArray(String, IntArray) et getIntArray(String) exactement comme les autres méthodes put et set:

val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
prefs.edit().putIntArray(INT_ARRAY_TEST_KEY, intArrayOf(1, 2, 3)).apply()
val intArray = prefs.getIntArray(INT_ARRAY_TEST_KEY)
0
Michael Geier

Vous ne pouvez enregistrer que les valeurs primitives dans sharedPreference. Utilisez Sqlite à la place.

0
Vineet Shukla