使用 parcelable 将项目存储为共享首选项?
Use parcelable to store item as sharedpreferences?
我的应用程序中有几个对象 Location 存储在 ArrayList 中,并使用 parcelable 在活动之间移动这些对象。该对象的代码如下所示:
public class Location implements Parcelable{
private double latitude, longitude;
private int sensors = 1;
private boolean day;
private int cloudiness;
/*
Måste ha samma ordning som writeToParcel för att kunna återskapa objektet.
*/
public Location(Parcel in){
this.latitude = in.readDouble();
this.longitude = in.readDouble();
this.sensors = in.readInt();
}
public Location(double latitude, double longitude){
super();
this.latitude = latitude;
this.longitude = longitude;
}
public void addSensors(){
sensors++;
}
public void addSensors(int i){
sensors = sensors + i;
}
+ Some getters and setters.
现在我需要更永久地存储这些对象。我在某处读到我可以序列化对象并保存为 sharedPreferences。我是否也必须实现 serializeable 或者我可以用 parcelable 做类似的事情?
Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.
由于 parcelable 无法将您的数据放入持久存储中(请参阅 StenSoft 的回答),您可以使用 gson 来持久化您的位置:
保存位置:
val json = Gson().toJson(location)
sharedPreferences.edit().putString("location", json).apply()
检索位置:
val json = sharedPreferences.getString("location", null)
return Gson().fromJson(json, Location::class.java)
如果您仍在使用 Java,请将 val
替换为 String
,将 Gson()
替换为 new Gson()
,将 ::class.java
替换为 .class
并以分号结束每一行。
首选方法是实施 IntentService 可能
如果您使用的是 Kotlin,我会采用 Cristan 的方法,但有一些扩展功能,请参阅:
import android.content.SharedPreferences
import android.os.Parcelable
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
fun SharedPreferences.Editor.putParcelable(key: String, parcelable: Parcelable) {
val json = Gson().toJson(parcelable)
putString(key, json)
}
inline fun <reified T : Parcelable?> SharedPreferences.getParcelable(key: String, default: T): T {
val json = getString(key, null)
return try {
if (json != null)
Gson().fromJson(json, T::class.java)
else default
} catch (_: JsonSyntaxException) {
default
}
}
然后您可以按如下方式使用它,用于存储:
sharedPreferences.edit {
putParcelable("location", location)
}
阅读方面:
val location = sharedPreferences.getParcelable<Location?>("location", null)
这是使用 Cristan 提案的一种非常干净的方式。希望它对你有用:)
您可以像
一样创建class Gson'able 和 Parcelable
@Parcelize
data class ApiRate(
@SerializedName("tp") val tp: Int,
@SerializedName("name") val name: String,
@SerializedName("from") val from: Int,
@SerializedName("currMnemFrom") val currMnemFrom: String,
@SerializedName("to") val to: Int,
@SerializedName("currMnemTo") val currMnemTo: String,
@SerializedName("basic") val basic: String,
@SerializedName("buy") val buy: String,
@SerializedName("sale") val sale: String,
@SerializedName("deltaBuy") val deltaBuy: String,
@SerializedName("deltaSell") val deltaSell: String
) : Parcelable
可能。
由于不应使用 Parcel 存储在共享首选项中,因此可以使用新的 Kotlin Serialization.
这里有两个将可序列化添加到共享首选项的扩展函数:
inline fun <reified S> SharedPreferences.getSerializable(key: String): S? {
return getString(key, null)?.let {
Json.decodeFromString(it) as? S
}
}
inline fun <reified S> SharedPreferences.putSerializable(key: String, value: S) {
val jsonString = Json.encodeToString(value)
edit().putString(key, jsonString).apply()
}
然后可以这样使用:
@Serializable
data class Location {
val double latitude,
val double longitude
}
val sharedPrefs = context.getSharedPreferences("mySharePrefs", Context.MODE_PRIVATE)
val location = Location(1.1, 2.2)
sharedPrefs.putSerializable("location", location)
val locationFromSharedPrefs = sharedPrefs.getSerializable<Location>("location")
我的应用程序中有几个对象 Location 存储在 ArrayList 中,并使用 parcelable 在活动之间移动这些对象。该对象的代码如下所示:
public class Location implements Parcelable{
private double latitude, longitude;
private int sensors = 1;
private boolean day;
private int cloudiness;
/*
Måste ha samma ordning som writeToParcel för att kunna återskapa objektet.
*/
public Location(Parcel in){
this.latitude = in.readDouble();
this.longitude = in.readDouble();
this.sensors = in.readInt();
}
public Location(double latitude, double longitude){
super();
this.latitude = latitude;
this.longitude = longitude;
}
public void addSensors(){
sensors++;
}
public void addSensors(int i){
sensors = sensors + i;
}
+ Some getters and setters.
现在我需要更永久地存储这些对象。我在某处读到我可以序列化对象并保存为 sharedPreferences。我是否也必须实现 serializeable 或者我可以用 parcelable 做类似的事情?
Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.
由于 parcelable 无法将您的数据放入持久存储中(请参阅 StenSoft 的回答),您可以使用 gson 来持久化您的位置:
保存位置:
val json = Gson().toJson(location)
sharedPreferences.edit().putString("location", json).apply()
检索位置:
val json = sharedPreferences.getString("location", null)
return Gson().fromJson(json, Location::class.java)
如果您仍在使用 Java,请将 val
替换为 String
,将 Gson()
替换为 new Gson()
,将 ::class.java
替换为 .class
并以分号结束每一行。
首选方法是实施 IntentService 可能
如果您使用的是 Kotlin,我会采用 Cristan 的方法,但有一些扩展功能,请参阅:
import android.content.SharedPreferences
import android.os.Parcelable
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
fun SharedPreferences.Editor.putParcelable(key: String, parcelable: Parcelable) {
val json = Gson().toJson(parcelable)
putString(key, json)
}
inline fun <reified T : Parcelable?> SharedPreferences.getParcelable(key: String, default: T): T {
val json = getString(key, null)
return try {
if (json != null)
Gson().fromJson(json, T::class.java)
else default
} catch (_: JsonSyntaxException) {
default
}
}
然后您可以按如下方式使用它,用于存储:
sharedPreferences.edit {
putParcelable("location", location)
}
阅读方面:
val location = sharedPreferences.getParcelable<Location?>("location", null)
这是使用 Cristan 提案的一种非常干净的方式。希望它对你有用:)
您可以像
一样创建class Gson'able 和 Parcelable@Parcelize
data class ApiRate(
@SerializedName("tp") val tp: Int,
@SerializedName("name") val name: String,
@SerializedName("from") val from: Int,
@SerializedName("currMnemFrom") val currMnemFrom: String,
@SerializedName("to") val to: Int,
@SerializedName("currMnemTo") val currMnemTo: String,
@SerializedName("basic") val basic: String,
@SerializedName("buy") val buy: String,
@SerializedName("sale") val sale: String,
@SerializedName("deltaBuy") val deltaBuy: String,
@SerializedName("deltaSell") val deltaSell: String
) : Parcelable
可能。
由于不应使用 Parcel 存储在共享首选项中,因此可以使用新的 Kotlin Serialization.
这里有两个将可序列化添加到共享首选项的扩展函数:
inline fun <reified S> SharedPreferences.getSerializable(key: String): S? {
return getString(key, null)?.let {
Json.decodeFromString(it) as? S
}
}
inline fun <reified S> SharedPreferences.putSerializable(key: String, value: S) {
val jsonString = Json.encodeToString(value)
edit().putString(key, jsonString).apply()
}
然后可以这样使用:
@Serializable
data class Location {
val double latitude,
val double longitude
}
val sharedPrefs = context.getSharedPreferences("mySharePrefs", Context.MODE_PRIVATE)
val location = Location(1.1, 2.2)
sharedPrefs.putSerializable("location", location)
val locationFromSharedPrefs = sharedPrefs.getSerializable<Location>("location")