使用Parcelable将项目存储为SharedPreferences?

31

我在我的应用程序中有一些存储在ArrayList中的对象,称为“位置”,并使用可包含性将它们在活动之间传递。该对象的代码如下所示:

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。我是否需要实现Serializable,还是可以使用Parcelable来做类似的事情?

6个回答

77

因为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,请使用String替换valnew Gson()替换Gson().class替换::class.java,并在每行结尾处加上分号。


一些问题出现在Gson().toJson(location)的使用中,它只返回空括号{},而实际上location是存在的。保存最佳位置Location[gps 37.343339,-122.097152 hAcc=1.7821856 et=+1m54s707ms alt=46.24608612060547 vel=0.6257401 mock] string>> {} - Arpit

40

来自Parcel文档

Parcel不是通用的序列化机制。这个类(以及为将任意对象放入Parcel而设计的相应的Parcelable API)旨在作为高性能IPC传输。因此,不适合将任何Parcel数据放入持久存储中: 对Parcel中任何数据的基础实现的更改可能会使较旧的数据无法读取。


啊!那样的话,我想我只能将它序列化了。 - xsiand
@xsiand 相关:https://dev59.com/Qm035IYBdhLWcg3wcvmS - Micro

2
如果您正在使用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提案的一种相当简洁的方法。希望对你有用 :)

请查看Gist:https://gist.github.com/ArnyminerZ/580ca9e9c404a172e583b922d453ca78 - Arnyminer Z

2

由于Parcel不应该用于存储在Shared Preferences中,一种替代方案是使用新的KotlinSerialization

以下是两个扩展函数,可将Serializable添加到Shared Preferences:

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")

0

你可以创建既能够被 Gson 处理,又能够被 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

可以的。


-5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接