Reputation: 22064
I know that SharedPreferences has putString()
, putFloat()
, putLong()
, putInt()
and putBoolean()
. But I need to store an object that is of type Serializable
in SharedPreferences
. How can I achieve this?
Upvotes: 54
Views: 36907
Reputation: 5059
If your object is complex with nested objects and you may need to remove a nested object one day then this is a bad mechanism, as you will need to implement your own migration strategy (unless throwing all the data away is fine).
If it is a large amount of data, this mechanism lacks transaction support. So do you write your own? Or use a more appropriate storage mechanism? I strongly encourage a more appropriate storage mechanism such as filesystem of SQLite DB.
Upvotes: 0
Reputation: 41
2020: If you want to save objects, then it's better to use Proto DataStore instead of SharedPreferences.
It brings great benefits over the “old” SharedPreferences, namely:
And many other perks such as transactional API, which guarantee consistency.
Check out my blog post to see how to implement Proto DataStore easily
Upvotes: 0
Reputation: 27970
We can create an easy to use syntax with 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)
}
and then save any Serializable to SharedPreferences
using similar get/put()
Complete gist here Save Serializables in Shared Preferences with Kotlin and GSON
As mentioned in other answers, you might have to consider migration when structure of data class changes. Or atleast would have to change key that you use to store.
Upvotes: 6
Reputation: 29783
The accepted answer is misleading, we can store serializable object into SharedPreferences by using GSON. Read more about it at google-gson.
you can add GSON dependency in Gradle file with:
compile 'com.google.code.gson:gson:2.7'
Here the snippet:
First, create your usual sharedPreferences:
//Creating a shared preference
SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);
Saving from serializable object to preference:
Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(YourSerializableObject);
prefsEditor.putString("SerializableObject", json);
prefsEditor.commit();
Get serializable object from preference:
Gson gson = new Gson();
String json = mPrefs.getString("SerializableObject", "");
yourSerializableObject = gson.fromJson(json, YourSerializableObject.class);
Upvotes: 52
Reputation: 2504
It is possible to do it without a file.
I'm serializing the information to base64 and like this I'm able to save it as a string in the preferences.
The following code is Serializing a serializable objec to base64 string and vice versa: 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;
}
}
Upvotes: 17
Reputation: 221
If you object is simple POJO you can convert object to JSON string and save it in shared preferences with putString().
Upvotes: 21
Reputation: 1516
In short you cant, try serializing your object to a private file, it amounts to the same thing. sample class below:
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;
}
}
Upvotes: 48