¿Es posible agregar una matriz u objeto a SharedPreferences en Android?

Respuestas:

59

Entonces, desde el sitio para desarrolladores de Android en Almacenamiento de datos :

Preferencias del usuario

Las preferencias compartidas no son estrictamente para guardar "preferencias de usuario" , como el tono de llamada que ha elegido un usuario. Si está interesado en crear preferencias de usuario para su aplicación, consulte PreferenceActivity, que proporciona un marco de actividad para que pueda crear preferencias de usuario, que se mantendrán automáticamente (utilizando preferencias compartidas).

Entonces creo que está bien, ya que son simplemente pares clave-valor los que persisten.

Para el cartel original, esto no es tan difícil. Simplemente repita la lista de matrices y agregue los elementos. En este ejemplo, utilizo un mapa por simplicidad, pero puede usar una lista de matrices y cambiarla adecuadamente:

// my list of names, icon locations
Map<String, String> nameIcons = new HashMap<String, String>();
nameIcons.put("Noel", "/location/to/noel/icon.png");
nameIcons.put("Bob", "another/location/to/bob/icon.png");
nameIcons.put("another name", "last/location/icon.png");

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

for (String s : nameIcons.keySet()) {
    // use the name as the key, and the icon as the value
    keyValuesEditor.putString(s, nameIcons.get(s));
}
keyValuesEditor.commit()

Haría algo similar para volver a leer los pares clave-valor. Hazme saber si esto funciona.

Actualización: si está utilizando API nivel 11 o posterior, existe un método para escribir un conjunto de cadenas

Navidad
fuente
Gracias Noel, lo descubrí con la ayuda de tu código. Sin embargo, observe los errores tipográficos del código. ;)
zsniperx
Funcionó como un encanto ... Thx
Bala Vishnu
74

Independientemente del nivel de API, compruebe las matrices de cadenas y las matrices de objetos en SharedPreferences


GUARDAR ARRAY

public boolean saveArray(String[] array, String arrayName, Context mContext) {   
    SharedPreferences prefs = mContext.getSharedPreferences("preferencename", 0);  
    SharedPreferences.Editor editor = prefs.edit();  
    editor.putInt(arrayName +"_size", array.length);  
    for(int i=0;i<array.length;i++)  
        editor.putString(arrayName + "_" + i, array[i]);  
    return editor.commit();  
} 

ARRAY DE CARGA

public String[] loadArray(String arrayName, Context mContext) {  
    SharedPreferences prefs = mContext.getSharedPreferences("preferencename", 0);  
    int size = prefs.getInt(arrayName + "_size", 0);  
    String array[] = new String[size];  
    for(int i=0;i<size;i++)  
        array[i] = prefs.getString(arrayName + "_" + i, null);  
    return array;  
}  
Sherif elKhatib
fuente
9
Esta es una técnica terrible. Vea los comentarios en ese blog: "El problema con este enfoque es que contaminará sus preferencias. Digamos, guarda una matriz con 100 entradas y luego la reduce a 2. Aún tendrá 100 entradas en sus preferencias a menos que límpialo primero ".
Kyle Ivey
2
La limpieza es una adición bastante fácil
Sherif elKhatib
Gracias, código de estilo muy agradable. Esta es una de mis respuestas favoritas aquí en SO. :)
Martin Pfeffer
3
¡Este es un enfoque incorrecto! intentas agregar 100 variables, ¡y esto es terrible! en su lugar, puede usar este método con jsonarray y jsonbj: stackoverflow.com/a/8287418/2652368
Amir Hossein Ghasemi
@AmirHosseinGhasemi ambos enfoques son en realidad hacks. gracias
Sherif elKhatib
60

Escribir,

SharedPreferences prefs = PreferenceManager
        .getDefaultSharedPreferences(this);
JSONArray jsonArray = new JSONArray();
jsonArray.put(1);
jsonArray.put(2);
Editor editor = prefs.edit();
editor.putString("key", jsonArray.toString());
System.out.println(jsonArray.toString());
editor.commit();

Leer,

try {
    JSONArray jsonArray2 = new JSONArray(prefs.getString("key", "[]"));
    for (int i = 0; i < jsonArray2.length(); i++) {
         Log.d("your JSON Array", jsonArray2.getInt(i)+"");
    }
} catch (Exception e) {
    e.printStackTrace();
}
Rohit
fuente
31

Las preferencias compartidas introdujeron métodos getStringSety putStringSeten el nivel de API 11, pero eso no es compatible con versiones anteriores de Android (que aún son populares) y también se limita a conjuntos de cadenas.

Android no proporciona mejores métodos, y recorrer mapas y arreglos para guardarlos y cargarlos no es muy fácil y limpio, especialmente para los arreglos. Pero una mejor implementación no es tan difícil:

package com.example.utils;

import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.content.SharedPreferences;

public class JSONSharedPreferences {
    private static final String PREFIX = "json";

    public static void saveJSONObject(Context c, String prefName, String key, JSONObject object) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(JSONSharedPreferences.PREFIX+key, object.toString());
        editor.commit();
    }

    public static void saveJSONArray(Context c, String prefName, String key, JSONArray array) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(JSONSharedPreferences.PREFIX+key, array.toString());
        editor.commit();
    }

    public static JSONObject loadJSONObject(Context c, String prefName, String key) throws JSONException {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        return new JSONObject(settings.getString(JSONSharedPreferences.PREFIX+key, "{}"));
    }

    public static JSONArray loadJSONArray(Context c, String prefName, String key) throws JSONException {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        return new JSONArray(settings.getString(JSONSharedPreferences.PREFIX+key, "[]"));
    }

    public static void remove(Context c, String prefName, String key) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        if (settings.contains(JSONSharedPreferences.PREFIX+key)) {
            SharedPreferences.Editor editor = settings.edit();
            editor.remove(JSONSharedPreferences.PREFIX+key);
            editor.commit();
        }
    }
}

Ahora puede guardar cualquier colección en preferencias compartidas con estos cinco métodos. Trabajar con JSONObjecty JSONArrayes muy fácil. Puede usar JSONArray (Collection copyFrom)el constructor público para hacer una JSONArraycolección de Java y usar JSONArraylos getmétodos para acceder a los elementos.

No hay límite de tamaño para las preferencias compartidas (además de los límites de almacenamiento del dispositivo), por lo que estos métodos pueden funcionar para la mayoría de los casos habituales en los que desea un almacenamiento rápido y fácil para alguna colección en su aplicación. Pero el análisis de JSON ocurre aquí, y las preferencias en Android se almacenan como XML internamente, por lo que recomiendo usar otros mecanismos de almacenamiento de datos persistentes cuando se trata de megabytes de datos.

Mostafa
fuente
7
Si va con JSON, tal vez consulte gson: code.google.com/p/google-gson : convierte objetos java hacia y desde JSON.
FeatureCreep
Sería una combinación interesante.
Mostafa
17

Modo fácil para el almacenamiento de objetos complejos con el uso de la biblioteca de Google Gson [1]

public static void setComplexObject(Context ctx, ComplexObject obj){
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
    SharedPreferences.Editor editor = preferences.edit();
    editor.putString("COMPLEX_OBJECT",new Gson().toJson(obj)); 
    editor.commit();
}

public static ComplexObject getComplexObject (Context ctx){
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
    String sobj = preferences.getString("COMPLEX_OBJECT", "");
    if(sobj.equals(""))return null;
    else return new Gson().fromJson(sobj, ComplexObject.class);
}

[1] http://code.google.com/p/google-gson/

Hpsaturn
fuente
¡El mejor! Marque esto como la RESPUESTA!
Renan Franca
3

Cargué una matriz de tamaños de cintura (ya creada en mi array.xml) en mi archivoferences.xml con el siguiente código. @ array / pant_inch_size es la identificación de toda la matriz.

 <ListPreference 
 android:title="choosepantsize"
 android:summary="Choose Pant Size"
 android:key="pantSizePref" 
 android:defaultValue="34" 
 android:entries="@array/pant_inch_size"
 android:entryValues="@array/pant_inch_size" /> 

Esto llenó el menú con opciones de la matriz. Establecí el tamaño predeterminado en 34, por lo que cuando aparece el menú, ven que el tamaño 34 está preseleccionado.

Keith
fuente
Hola Keith, gracias por tu respuesta. Necesito almacenar un pedido y no trabajo con la interfaz de usuario de preferencia, por lo que no creo que su código coincida con lo que necesito lograr. Gracias de todos modos
zsniperx
ah !! Malinterpreté tu pregunta, lo siento. Para cualquier otro lector, mi código XML simplemente toma elementos de mi archivo array.xml y los carga en el menú de preferencias, con la preferencia predeterminada preseleccionada como "34" en este caso. Luego utilizo Java para encontrar el identificador de esta preferencia particular, que es "pantSizePref" (la "clave").
Keith
2

La forma simple es convertirlo a JSON String como el siguiente ejemplo:

Gson gson = new Gson();
String json = gson.toJson(myObj);

Luego, guarde la cadena en las preferencias compartidas. Una vez que lo necesite, simplemente obtenga la cadena de las preferencias compartidas y conviértala de nuevo a JSONArray o JSONObject (según sus requisitos).

Gaurav Darji
fuente
2

Para la escritura:

 private <T> void storeData(String key, T data) {
    ByteArrayOutputStream serializedData = new ByteArrayOutputStream();

    try {
        ObjectOutputStream serializer = new ObjectOutputStream(serializedData);
        serializer.writeObject(data);
    } catch (IOException e) {
        e.printStackTrace();
    }

    SharedPreferences sharedPreferences = getSharedPreferences(TAG, 0);
    SharedPreferences.Editor edit = sharedPreferences.edit();

    edit.putString(key, Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT));
    edit.commit();
}

Para leer:

private <T> T getStoredData(String key) {
    SharedPreferences sharedPreferences = getSharedPreferences(TAG, 0);
    String serializedData = sharedPreferences.getString(key, null);
    T storedData = null;
    try {
        ByteArrayInputStream input = new ByteArrayInputStream(Base64.decode(serializedData, Base64.DEFAULT));
        ObjectInputStream inputStream = new ObjectInputStream(input);
        storedData = (T)inputStream.readObject();
    } catch (IOException|ClassNotFoundException|java.lang.IllegalArgumentException e) {
        e.printStackTrace();
    }

    return storedData;
}
Benav
fuente
Esto parece una buena sugerencia. Todas las colecciones comunes implementan serializables, y su cadena, número y fecha básicos son serializables. El único inconveniente sería el rendimiento.
androidguy
1

Este es el código de preferencias compartidas que utilizo con éxito, consulte este enlace :

  public class MainActivity extends Activity {

private static final int RESULT_SETTINGS = 1;
Button button;
public String a="dd";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

 button = (Button) findViewById(R.id.btnoptions);


setContentView(R.layout.activity_main);

  // showUserSettings();
  }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return true;
 }

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {

case R.id.menu_settings:
 Intent i = new Intent(this, UserSettingActivity.class);
 startActivityForResult(i, RESULT_SETTINGS);
 break;

 }

return true;
}

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data)     {
  super.onActivityResult(requestCode, resultCode, data);

 switch (requestCode) {
 case RESULT_SETTINGS:
 showUserSettings();
 break;

 } 

  }

  private void showUserSettings() {
 SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);

 StringBuilder builder = new StringBuilder();

 builder.append("\n Pet: "
  + sharedPrefs.getString("prefpetname", "NULL"));

 builder.append("\n Address:"
 + sharedPrefs.getString("prefaddress","NULL" ));

 builder.append("\n Your name: "
 + sharedPrefs.getString("prefname", "NULL"));

 TextView settingsTextView = (TextView) findViewById(R.id.textUserSettings);


  settingsTextView.setText(builder.toString());


    }

   }

¡FELIZ CODIFICACIÓN!

dondondon
fuente
0

Puede usar putStringSet

Esto le permite guardar un HashSet en sus preferencias, así:

Salvar

Set<String> values;

SharedPreferences sharedPref = 
    mContext.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);

Editor editor = sharedPref.edit();

editor.putStringSet("YOUR_KEY", values);
editor.apply();

Recuperar

SharedPreferences sharedPref = 
    mContext.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);

Editor editor = sharedPref.edit();

Set<String> newList = editor.getStringSet("YOUR_KEY", null);

PutStringSet permite solo un Set y esta es una lista desordenada .

Daniel Beltrami
fuente
0

Cuando me molestaron con esto, obtuve la solución de serialización donde puedes serializar tu cadena, pero también se me ocurrió un truco.

Lea esto solo si no ha leído sobre la serialización, de lo contrario, baje y lea mi truco

Para almacenar los elementos de la matriz en orden, podemos serializar la matriz en una sola cadena (creando una nueva clase ObjectSerializer (copie el código de - www.androiddevcourse.com/objectserializer.html, reemplace todo excepto el nombre del paquete))

Ingresando datos en preferencia compartida: ingrese la descripción de la imagen aquí

el resto del código en la línea 38 - ingrese la descripción de la imagen aquí

Coloque el siguiente argumento como este, de modo que si los datos no se recuperan, devolverán una matriz vacía (no podemos poner una cadena vacía porque el contenedor / variable es una matriz, no una cadena)

Viniendo a mi Hack: -

Combine el contenido de la matriz en una sola cadena colocando algún símbolo entre cada elemento y luego divídalo usando ese símbolo cuando lo recupere. Porque agregar y recuperar String es fácil con preferencias compartidas. Si le preocupa dividir, busque "dividir una cadena en Java".

[Nota: Esto funciona bien si el contenido de su matriz es de tipo primitivo como string, int, float, etc. Funcionará para matrices complejas que tienen su propia estructura, suponga una guía telefónica, pero la fusión y división se convertiría en una poco complejo. ]

PD: Soy nuevo en Android, así que no sé si es un buen truco, así que déjame saber si encuentras mejores trucos.

Ritveak
fuente