我需要在许多地方获得用户对象,其中包含许多字段。登录后,我想保存/存储这些用户对象。我们如何实现这种场景?
我不能这样存储它:
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putString("BusinessUnit", strBusinessUnit);
我需要在许多地方获得用户对象,其中包含许多字段。登录后,我想保存/存储这些用户对象。我们如何实现这种场景?
我不能这样存储它:
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putString("BusinessUnit", strBusinessUnit);
当前回答
另一种不使用Json格式保存和恢复android sharedpreferences对象的方法
private static ExampleObject getObject(Context c,String db_name){
SharedPreferences sharedPreferences = c.getSharedPreferences(db_name, Context.MODE_PRIVATE);
ExampleObject o = new ExampleObject();
Field[] fields = o.getClass().getFields();
try {
for (Field field : fields) {
Class<?> type = field.getType();
try {
final String name = field.getName();
if (type == Character.TYPE || type.equals(String.class)) {
field.set(o,sharedPreferences.getString(name, ""));
} else if (type.equals(int.class) || type.equals(Short.class))
field.setInt(o,sharedPreferences.getInt(name, 0));
else if (type.equals(double.class))
field.setDouble(o,sharedPreferences.getFloat(name, 0));
else if (type.equals(float.class))
field.setFloat(o,sharedPreferences.getFloat(name, 0));
else if (type.equals(long.class))
field.setLong(o,sharedPreferences.getLong(name, 0));
else if (type.equals(Boolean.class))
field.setBoolean(o,sharedPreferences.getBoolean(name, false));
else if (type.equals(UUID.class))
field.set(
o,
UUID.fromString(
sharedPreferences.getString(
name,
UUID.nameUUIDFromBytes("".getBytes()).toString()
)
)
);
} catch (IllegalAccessException e) {
Log.e(StaticConfig.app_name, "IllegalAccessException", e);
} catch (IllegalArgumentException e) {
Log.e(StaticConfig.app_name, "IllegalArgumentException", e);
}
}
} catch (Exception e) {
System.out.println("Exception: " + e);
}
return o;
}
private static void setObject(Context context, Object o, String db_name) {
Field[] fields = o.getClass().getFields();
SharedPreferences sp = context.getSharedPreferences(db_name, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
for (Field field : fields) {
Class<?> type = field.getType();
try {
final String name = field.getName();
if (type == Character.TYPE || type.equals(String.class)) {
Object value = field.get(o);
if (value != null)
editor.putString(name, value.toString());
} else if (type.equals(int.class) || type.equals(Short.class))
editor.putInt(name, field.getInt(o));
else if (type.equals(double.class))
editor.putFloat(name, (float) field.getDouble(o));
else if (type.equals(float.class))
editor.putFloat(name, field.getFloat(o));
else if (type.equals(long.class))
editor.putLong(name, field.getLong(o));
else if (type.equals(Boolean.class))
editor.putBoolean(name, field.getBoolean(o));
else if (type.equals(UUID.class))
editor.putString(name, field.get(o).toString());
} catch (IllegalAccessException e) {
Log.e(StaticConfig.app_name, "IllegalAccessException", e);
} catch (IllegalArgumentException e) {
Log.e(StaticConfig.app_name, "IllegalArgumentException", e);
}
}
editor.apply();
}
其他回答
您可以使用gson.jar将类对象存储到SharedPreferences中。 你可以从google-gson下载这个罐子
或者在Gradle文件中添加GSON依赖项:
implementation 'com.google.code.gson:gson:2.8.8'
你可以在这里找到最新的版本
创建共享首选项:
SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);
保存:
MyObject myObject = new MyObject;
//set variables of 'myObject', etc.
Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject);
prefsEditor.putString("MyObject", json);
prefsEditor.commit();
检索:
Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);
更好的方法是创建一个全局Constants类来保存键或变量以获取或保存数据。
要保存数据,请调用此方法保存来自任何地方的数据。
public static void saveData(Context con, String variable, String data)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(con);
prefs.edit().putString(variable, data).commit();
}
用它来获取数据。
public static String getData(Context con, String variable, String defaultValue)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(con);
String data = prefs.getString(variable, defaultValue);
return data;
}
像这样的方法就可以了
public static User getUserInfo(Context con)
{
String id = getData(con, Constants.USER_ID, null);
String name = getData(con, Constants.USER_NAME, null);
if(id != null && name != null)
{
User user = new User(); //Hope you will have a user Object.
user.setId(id);
user.setName(name);
//Here set other credentials.
return user;
}
else
return null;
}
如果你的对象很复杂,我建议序列化/XML/JSON,并将这些内容保存到SD卡。你可以在这里找到关于如何保存到外部存储的其他信息: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
使用delegate Kotlin,我们可以轻松地从共享首选项中放置和获取数据。
inline fun <reified T> Context.sharedPrefs(key: String) = object : ReadWriteProperty<Any?, T> {
val sharedPrefs by lazy { this@sharedPrefs.getSharedPreferences("APP_DATA", Context.MODE_PRIVATE) }
val gson by lazy { Gson() }
var newData: T = (T::class.java).newInstance()
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return getPrefs()
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.newData = value
putPrefs(newData)
}
fun putPrefs(value: T?) {
sharedPrefs.edit {
when (value) {
is Int -> putInt(key, value)
is Boolean -> putBoolean(key, value)
is String -> putString(key, value)
is Long -> putLong(key, value)
is Float -> putFloat(key, value)
is Parcelable -> putString(key, gson.toJson(value))
else -> throw Throwable("no such type exist to put data")
}
}
}
fun getPrefs(): T {
return when (newData) {
is Int -> sharedPrefs.getInt(key, 0) as T
is Boolean -> sharedPrefs.getBoolean(key, false) as T
is String -> sharedPrefs.getString(key, "") as T ?: "" as T
is Long -> sharedPrefs.getLong(key, 0L) as T
is Float -> sharedPrefs.getFloat(key, 0.0f) as T
is Parcelable -> gson.fromJson(sharedPrefs.getString(key, "") ?: "", T::class.java)
else -> throw Throwable("no such type exist to put data")
} ?: newData
}
}
//use this delegation in activity and fragment in following way
var ourData by sharedPrefs<String>("otherDatas")
下面是我从这里获得的Kotlin Delegated Properties的使用方法,但扩展了它,并允许使用一种简单的机制来获取/设置SharedPreference属性。
对于String, Int, Long, Float或Boolean,它使用标准的SharePreference getter和setter。然而,对于所有其他数据类,它使用GSON序列化为一个String,用于setter。然后为getter反序列化为数据对象。
与其他解决方案类似,这需要在gradle文件中添加GSON作为依赖项:
implementation 'com.google.code.gson:gson:2.8.6'
下面是一个简单的数据类的例子,我们希望能够保存并存储到SharedPreferences:
data class User(val first: String, val last: String)
下面是一个实现属性委托的类:
object UserPreferenceProperty : PreferenceProperty<User>(
key = "USER_OBJECT",
defaultValue = User(first = "Jane", last = "Doe"),
clazz = User::class.java)
object NullableUserPreferenceProperty : NullablePreferenceProperty<User?, User>(
key = "NULLABLE_USER_OBJECT",
defaultValue = null,
clazz = User::class.java)
object FirstTimeUser : PreferenceProperty<Boolean>(
key = "FIRST_TIME_USER",
defaultValue = false,
clazz = Boolean::class.java
)
sealed class PreferenceProperty<T : Any>(key: String,
defaultValue: T,
clazz: Class<T>) : NullablePreferenceProperty<T, T>(key, defaultValue, clazz)
@Suppress("UNCHECKED_CAST")
sealed class NullablePreferenceProperty<T : Any?, U : Any>(private val key: String,
private val defaultValue: T,
private val clazz: Class<U>) : ReadWriteProperty<Any, T> {
override fun getValue(thisRef: Any, property: KProperty<*>): T = HandstandApplication.appContext().getPreferences()
.run {
when {
clazz.isAssignableFrom(String::class.java) -> getString(key, defaultValue as String?) as T
clazz.isAssignableFrom(Int::class.java) -> getInt(key, defaultValue as Int) as T
clazz.isAssignableFrom(Long::class.java) -> getLong(key, defaultValue as Long) as T
clazz.isAssignableFrom(Float::class.java) -> getFloat(key, defaultValue as Float) as T
clazz.isAssignableFrom(Boolean::class.java) -> getBoolean(key, defaultValue as Boolean) as T
else -> getObject(key, defaultValue, clazz)
}
}
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) = HandstandApplication.appContext().getPreferences()
.edit()
.apply {
when {
clazz.isAssignableFrom(String::class.java) -> putString(key, value as String?) as T
clazz.isAssignableFrom(Int::class.java) -> putInt(key, value as Int) as T
clazz.isAssignableFrom(Long::class.java) -> putLong(key, value as Long) as T
clazz.isAssignableFrom(Float::class.java) -> putFloat(key, value as Float) as T
clazz.isAssignableFrom(Boolean::class.java) -> putBoolean(key, value as Boolean) as T
else -> putObject(key, value)
}
}
.apply()
private fun Context.getPreferences(): SharedPreferences = getSharedPreferences(APP_PREF_NAME, Context.MODE_PRIVATE)
private fun <T, U> SharedPreferences.getObject(key: String, defValue: T, clazz: Class<U>): T =
Gson().fromJson(getString(key, null), clazz) as T ?: defValue
private fun <T> SharedPreferences.Editor.putObject(key: String, value: T) = putString(key, Gson().toJson(value))
companion object {
private const val APP_PREF_NAME = "APP_PREF"
}
}
注意:您不需要更新密封类中的任何内容。委托的属性是对象/单例的UserPreferenceProperty, NullableUserPreferenceProperty和FirstTimeUser。
为了从SharedPreferences中保存/获取一个新的数据对象,现在只需要添加四行就可以了:
object NewPreferenceProperty : PreferenceProperty<String>(
key = "NEW_PROPERTY",
defaultValue = "",
clazz = String::class.java)
最后,你可以通过使用by关键字来读取/写入SharedPreferences的值:
private var user: User by UserPreferenceProperty
private var nullableUser: User? by NullableUserPreferenceProperty
private var isFirstTimeUser: Boolean by
Log.d("TAG", user) // outputs the `defaultValue` for User the first time
user = User(first = "John", last = "Doe") // saves this User to the Shared Preferences
Log.d("TAG", user) // outputs the newly retrieved User (John Doe) from Shared Preferences