【问题标题】:Use parcelable to store item as sharedpreferences?使用 parcelable 将项目存储为共享首选项?
【发布时间】:2015-04-10 22:02:03
【问题描述】:

我的应用中有几个对象 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。我是否也必须实现可序列化,或者我可以用 parcelable 做类似的事情?

【问题讨论】:

    标签: java android storage serializable


    【解决方案1】:

    由于 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,并以分号结束每一行。

    【讨论】:

      【解决方案2】:

      来自documentation of Parcel

      Parcel 不是通用的序列化机制。此类(以及用于将任意对象放入 Parcel 的相应 Parcelable API)被设计为高性能 IPC 传输。因此,将任何 Parcel 数据放入持久存储是不合适的:Parcel 中任何数据的底层实现发生变化都可能导致旧数据不可读。

      【讨论】:

      【解决方案3】:

      如果你在使用 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 提案的一种非常简洁的方式。希望它对你有用:)

      【解决方案4】:

      由于不应将 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")
      

      【讨论】:

        【解决方案5】:

        您可以像 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
        

        有可能。

        【讨论】:

          【解决方案6】:

          首选方法是实现IntentService 可能

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-09-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-03
            • 1970-01-01
            相关资源
            最近更新 更多