¿Cómo guardar HashMap en preferencias compartidas?

Respuestas:

84

No recomendaría escribir objetos complejos en SharedPreference. En su lugar, usaría ObjectOutputStreampara escribirlo en la memoria interna.

File file = new File(getDir("data", MODE_PRIVATE), "map");    
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
outputStream.writeObject(map);
outputStream.flush();
outputStream.close();
Kirill Rakhman
fuente
6
Con un ObjectInputStream.
Kirill Rakhman
5
aquí hay un ejemplo de cómo usar ObjectOutputStream y ObjectInputStream juntos: tutorialspoint.com/java/io/objectinputstream_readobject.htm
Krzysztof Skrzynecki
¿Desde cuándo Hashmap es un objeto complejo? ¿Cómo asumiste esto?
Pedro Paulo Amorim
78

Yo uso Gsonpara convertir HashMapa Stringy luego guardarlo paraSharedPrefs

private void hashmaptest()
{
    //create test hashmap
    HashMap<String, String> testHashMap = new HashMap<String, String>();
    testHashMap.put("key1", "value1");
    testHashMap.put("key2", "value2");

    //convert to string using gson
    Gson gson = new Gson();
    String hashMapString = gson.toJson(testHashMap);

    //save in shared prefs
    SharedPreferences prefs = getSharedPreferences("test", MODE_PRIVATE);
    prefs.edit().putString("hashString", hashMapString).apply();

    //get from shared prefs
    String storedHashMapString = prefs.getString("hashString", "oopsDintWork");
    java.lang.reflect.Type type = new TypeToken<HashMap<String, String>>(){}.getType();
    HashMap<String, String> testHashMap2 = gson.fromJson(storedHashMapString, type);

    //use values
    String toastString = testHashMap2.get("key1") + " | " + testHashMap2.get("key2");
    Toast.makeText(this, toastString, Toast.LENGTH_LONG).show();
}
penduDev
fuente
2
cómo obtener hashmap de gson recibí un mensaje de error como com.qb.gson.JsonSyntaxException: java.lang.IllegalStateException: se esperaba BEGIN_OBJECT pero estaba BEGIN_ARRAY en la línea 1 columna 2 -
Ram
Se esperaba BEGIN_OBJECT pero estaba BEGIN_ARRAY está sucediendo porque HashMap <String, String> debería ser HashMap <String, Object>, si los valores son siempre String object, no tendrá ningún problema, pero si el valor de alguna clave es diff, entonces String (por ejemplo objeto personalizado, lista o matriz), se lanzará una excepción. Entonces, para poder analizar todo lo que necesita HashMap <String, Object>
Stoycho Andreev
43

He escrito un código simple para guardar el mapa de preferencia y cargar el mapa de preferencia. No se requieren funciones GSON o Jackson. Acabo de usar un mapa que tiene String como clave y Boolean como valor.

private void saveMap(Map<String,Boolean> inputMap){
  SharedPreferences pSharedPref = getApplicationContext().getSharedPreferences("MyVariables", Context.MODE_PRIVATE);
  if (pSharedPref != null){
    JSONObject jsonObject = new JSONObject(inputMap);
    String jsonString = jsonObject.toString();
    Editor editor = pSharedPref.edit();
    editor.remove("My_map").commit();
    editor.putString("My_map", jsonString);
    editor.commit();
  }
}

private Map<String,Boolean> loadMap(){
  Map<String,Boolean> outputMap = new HashMap<String,Boolean>();
  SharedPreferences pSharedPref = getApplicationContext().getSharedPreferences("MyVariables", Context.MODE_PRIVATE);
  try{
    if (pSharedPref != null){       
      String jsonString = pSharedPref.getString("My_map", (new JSONObject()).toString());
      JSONObject jsonObject = new JSONObject(jsonString);
      Iterator<String> keysItr = jsonObject.keys();
      while(keysItr.hasNext()) {
        String key = keysItr.next();
        Boolean value = (Boolean) jsonObject.get(key);
        outputMap.put(key, value);
      }
    }
  }catch(Exception e){
    e.printStackTrace();
  }
  return outputMap;
}
Vinoj John Hosan
fuente
respuesta perfecta :)
Ramkesh Yadav
¿Cómo puedo acceder getApplicationContextdesde una clase sencilla?
Dmitry
@Dmitry Un atajo: en su clase simple, incluya el método de contexto establecido y establezca el contexto como variable miembro y utilícelo en consecuencia
Vinoj John Hosan
32
Map<String, String> aMap = new HashMap<String, String>();
aMap.put("key1", "val1");
aMap.put("key2", "val2");
aMap.put("Key3", "val3");

SharedPreferences keyValues = getContext().getSharedPreferences("Your_Shared_Prefs"), Context.MODE_PRIVATE);
SharedPreferences.Editor keyValuesEditor = keyValues.edit();

for (String s : aMap.keySet()) {
    keyValuesEditor.putString(s, aMap.get(s));
}

keyValuesEditor.commit();
hovanessyan
fuente
pero necesito guardar el mapa hash como sí mismo, como si
agreguemos un
de lo que probablemente deba usar la serialización y guardar el HashMap serializado en SharedPrefs. Puede encontrar fácilmente ejemplos de código sobre cómo hacerlo.
hovanessyan
11

Como resultado de la respuesta de Vinoj John Hosan, modifiqué la respuesta para permitir inserciones más genéricas, basadas en la clave de los datos, en lugar de una única clave como "My_map".

En mi implementación, MyAppes mi Applicationclase de invalidación y MyApp.getInstance()actúa para devolver el context.

public static final String USERDATA = "MyVariables";

private static void saveMap(String key, Map<String,String> inputMap){
    SharedPreferences pSharedPref = MyApp.getInstance().getSharedPreferences(USERDATA, Context.MODE_PRIVATE);
    if (pSharedPref != null){
        JSONObject jsonObject = new JSONObject(inputMap);
        String jsonString = jsonObject.toString();
        SharedPreferences.Editor editor = pSharedPref.edit();
        editor.remove(key).commit();
        editor.putString(key, jsonString);
        editor.commit();
    }
}

private static Map<String,String> loadMap(String key){
    Map<String,String> outputMap = new HashMap<String,String>();
    SharedPreferences pSharedPref = MyApp.getInstance().getSharedPreferences(USERDATA, Context.MODE_PRIVATE);
    try{
        if (pSharedPref != null){
            String jsonString = pSharedPref.getString(key, (new JSONObject()).toString());
            JSONObject jsonObject = new JSONObject(jsonString);
            Iterator<String> keysItr = jsonObject.keys();
            while(keysItr.hasNext()) {
                String k = keysItr.next();
                String v = (String) jsonObject.get(k);
                outputMap.put(k,v);
            }
        }
    }catch(Exception e){
        e.printStackTrace();
    }
    return outputMap;
}
Kyle Falconer
fuente
¿Cómo puedo acceder a MyApp desde una biblioteca?
Dmitry
@Dmitry Haría esto de la misma manera que accedería a la Contextinstancia desde una biblioteca. Consulte esta otra pregunta de SO: ¿Es posible obtener el contexto de la aplicación en un proyecto de biblioteca de Android?
Kyle Falconer
2

En su lugar, podría intentar usar JSON.

Para ahorrar

try {
    HashMap<Integer, String> hash = new HashMap<>();
    JSONArray arr = new JSONArray();
    for(Integer index : hash.keySet()) {
        JSONObject json = new JSONObject();
        json.put("id", index);
        json.put("name", hash.get(index));
        arr.put(json);
    }
    getSharedPreferences(INSERT_YOUR_PREF).edit().putString("savedData", arr.toString()).apply();
} catch (JSONException exception) {
    // Do something with exception
}

Por conseguir

try {
    String data = getSharedPreferences(INSERT_YOUR_PREF).getString("savedData");
    HashMap<Integer, String> hash = new HashMap<>();
    JSONArray arr = new JSONArray(data);
    for(int i = 0; i < arr.length(); i++) {
        JSONObject json = arr.getJSONObject(i);
        hash.put(json.getInt("id"), json.getString("name"));
    }
} catch (Exception e) {
    e.printStackTrace();
}
Jonas Borggren
fuente
1
String converted = new Gson().toJson(map);
SharedPreferences sharedPreferences = getSharedPreferences("sharepref",Context.MODE_PRIVATE);
sharedPreferences.edit().putString("yourkey",converted).commit();

fuente
1
¿Cómo devolverlo al mapa?
زياد
1

Usando PowerPreference .

Guardar datos

HashMap<String, Object> hashMap = new HashMap<String, Object>();
PowerPreference.getDefaultFile().put("key",hashMap);

Leer datos

HashMap<String, Object> value = PowerPreference.getDefaultFile().getMap("key", HashMap.class, String.class, Object.class);
Ali Asadi
fuente
1

mapa -> cadena

val jsonString: String  = Gson().toJson(map)
preferences.edit().putString("KEY_MAP_SAVE", jsonString).apply()

cadena -> mapa

val jsonString: String = preferences.getString("KEY_MAP_SAVE", JSONObject().toString())
val listType = object : TypeToken<Map<String, String>>() {}.type
return Gson().fromJson(jsonString, listType)
Evgen Pero
fuente
0

Puede usar esto en un archivo de preferencias compartido dedicado (fuente: https://developer.android.com/reference/android/content/SharedPreferences.html ):

obtener toda

agregado en el nivel de API 1 Map getAll () Recupera todos los valores de las preferencias.

Tenga en cuenta que no debe modificar la colección devuelta por este método ni alterar ninguno de sus contenidos. La coherencia de sus datos almacenados no está garantizada si lo hace.

Devuelve el mapa Devuelve un mapa que contiene una lista de pares clave / valor que representan las preferencias.

sivi
fuente
0

La forma perezosa: almacenar cada clave directamente en SharedPreferences

Para el caso de uso limitado en el que su mapa solo va a tener no más de unas pocas docenas de elementos, puede aprovechar el hecho de que SharedPreferences funciona de manera muy similar a un mapa y simplemente almacenar cada entrada bajo su propia clave:

Almacenamiento del mapa

Map<String, String> map = new HashMap<String, String>();
map.put("color", "red");
map.put("type", "fruit");
map.put("name", "Dinsdale");


SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// OR use a specific pref name
// context.getSharedPreferences("myMegaMap");

for (Map.Entry<String, String> entry : map.entrySet()) {
    prefs.edit().putString(entry.getKey(), entry.getValue());
}

Leyendo claves del mapa

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// OR use a specific pref name
// context.getSharedPreferences("myMegaMap");
prefs.getString("color", "pampa");

En caso de que utilice un nombre de preferencia personalizado (es decir context.getSharedPreferences("myMegaMap")), también puede obtener todas las claves conprefs.getAll()

Sus valores pueden ser de cualquier tipo compatible con SharedPreferences: String, int, long, float, boolean.

ccpizza
fuente
0

Sé que es un poco tarde, pero espero que esto pueda ser útil para cualquiera que lea ...

entonces lo que hago es

1) Cree HashMapa y agregue datos como: -

HashMap hashmapobj = new HashMap();
  hashmapobj.put(1001, "I");
  hashmapobj.put(1002, "Love");
  hashmapobj.put(1003, "Java");

2) Escríbalo para compartir el editor de preferencias como: -

SharedPreferences sharedpreferences = getSharedPreferences(MyPREFERENCES,Context.MODE_PRIVATE);
    Editor editor = sharedpreferences.edit();
    editor.putStringSet("key", hashmapobj );
    editor.apply(); //Note: use commit if u wan to receive response from shp

3) Leer datos como: - en una nueva clase donde desea que se lean

   HashMap hashmapobj_RECIVE = new HashMap();
     SharedPreferences sharedPreferences (MyPREFERENCES,Context.MODE_PRIVATE;
     //reading HashMap  from sharedPreferences to new empty HashMap  object
     hashmapobj_RECIVE = sharedpreferences.getStringSet("key", null);
TPX
fuente