54 votes

Android - SharedPreferences avec un objet sérialisable

Je sais que les préférences partagées ont putString() , putFloat() , putLong() , putInt() y putBoolean() . Mais j'ai besoin de stocker un objet de type Serializable en SharedPreferences . Comment y parvenir ?

51voto

La réponse acceptée est trompeuse, nous pouvons stocker un objet sérialisable dans SharedPreferences en utilisant GSON. Pour en savoir plus, consultez le site google-gson .

vous pouvez ajouter la dépendance GSON dans le fichier Gradle avec :

compile 'com.google.code.gson:gson:2.7'

Voici l'extrait :

Tout d'abord, créez vos préférences partagées habituelles :

//Creating a shared preference
SharedPreferences  mPrefs = getPreferences(MODE_PRIVATE);

Sauvegarde d'un objet sérialisable vers une préférence :

 Editor prefsEditor = mPrefs.edit();
 Gson gson = new Gson();
 String json = gson.toJson(YourSerializableObject);
 prefsEditor.putString("SerializableObject", json);
 prefsEditor.commit();

Obtention d'un objet sérialisable à partir de la préférence :

Gson gson = new Gson();
String json = mPrefs.getString("SerializableObject", "");
yourSerializableObject = gson.fromJson(json, YourSerializableObject.class);

48voto

Chris.D Points 985

En bref, vous ne pouvez pas, essayez de sérialiser votre objet dans un fichier privé, cela revient au même. exemple de classe ci-dessous :

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import android.app.Activity;
import android.content.Context;

/**
 *
 * Writes/reads an object to/from a private local file
 * 
 *
 */
public class LocalPersistence {

    /**
     * 
     * @param context
     * @param object
     * @param filename
     */
    public static void witeObjectToFile(Context context, Object object, String filename) {

        ObjectOutputStream objectOut = null;
        try {

            FileOutputStream fileOut = context.openFileOutput(filename, Activity.MODE_PRIVATE);
            objectOut = new ObjectOutputStream(fileOut);
            objectOut.writeObject(object);
            fileOut.getFD().sync();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (objectOut != null) {
                try {
                    objectOut.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }
    }

    /**
     * 
     * @param context
     * @param filename
     * @return
     */
    public static Object readObjectFromFile(Context context, String filename) {

        ObjectInputStream objectIn = null;
        Object object = null;
        try {

            FileInputStream fileIn = context.getApplicationContext().openFileInput(filename);
            objectIn = new ObjectInputStream(fileIn);
            object = objectIn.readObject();

        } catch (FileNotFoundException e) {
            // Do nothing
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (objectIn != null) {
                try {
                    objectIn.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }

        return object;
    }

}

0 votes

Doit filename dans votre code soit un chemin absolu (par exemple : "/data/com.example.myapp/foobar.dat"), ou doit-il être relatif (par exemple : "foobar.dat") ?

3 votes

Juste un nom de fichier, les séparateurs de chemin ne sont pas autorisés, comme indiqué dans la documentation de l'API. [developer.Android.com/reference/Android/content/](http://developer.android.com/reference/android/content/Context.html#openFileOutput(java.lang.String) , int)

1 votes

Comment puis-je supprimer un fichier sauvegardé par votre méthode ci-dessus ?

20voto

user2139213 Points 81

Si votre objet est un simple POJO, vous pouvez convertir l'objet en chaîne JSON et l'enregistrer dans les préférences partagées avec putString().

17voto

Il est possible de le faire sans fichier.

Je sérialise l'information en base64 et comme cela, je peux l'enregistrer en tant que chaîne de caractères dans les préférences.

Le code suivant est import Android.util.Base64 ;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectSerializerHelper {
    static public String objectToString(Serializable object) {
        String encoded = null;
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(object);
            objectOutputStream.close();
            encoded = new String(Base64.encodeToString(byteArrayOutputStream.toByteArray(),0));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return encoded;
    }

    @SuppressWarnings("unchecked")
    static public Serializable stringToObject(String string){
        byte[] bytes = Base64.decode(string,0);
        Serializable object = null;
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream( new ByteArrayInputStream(bytes) );
            object = (Serializable)objectInputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
        return object;
    }

}

0 votes

La classe ci-dessus peut être collée dans votre classe POJO et vous pouvez facilement mettre en œuvre les éléments suivants public YourPojo getFromPreferences(Context context) y public void saveToPreferences(Context context) qui utilise les deux méthodes ci-dessus, ainsi que la méthode PreferenceManager.getDefaultSharedPreferences(context)

5voto

Shardul Points 10371

Nous pouvons créer une syntaxe facile à utiliser avec Kotlin.

@Throws(JsonIOException::class)
fun Serializable.toJson(): String {
   return Gson().toJson(this)
}

@Throws(JsonSyntaxException::class)
 fun <T> String.to(type: Class<T>): T where T : Serializable {
 return Gson().fromJson(this, type)
}

@Throws(JsonIOException::class)
fun SharedPreferences.Editor.putSerializable(key: String, o: Serializable?) = apply {
   putString(key, o?.toJson())
}

@Throws(JsonSyntaxException::class)
   fun <T> SharedPreferences.getSerializable(key: String, type: Class<T>): T? where T : Serializable {
    return getString(key, null)?.to(type)
}

puis enregistrer tout Serializable dans SharedPreferences en utilisant des get/put()

L'essentiel ici Sauvegarder les Serializables dans les préférences partagées avec Kotlin et GSON

Comme indiqué dans d'autres réponses, vous devrez peut-être envisager une migration lorsque la structure de la classe de données change. Ou au moins, vous devrez changer la clé que vous utilisez pour stocker.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X