【问题标题】:Store a collection of objects in SharedPreferences在 SharedPreferences 中存储对象集合
【发布时间】:2016-07-19 12:47:09
【问题描述】:

我正在开发一个用于在 SharedPreferences 中存储数据的实用程序类。到现在为止,我已经能够创建一个通用函数来存储和检索 String、int 和 boolean。是否有一种通用的方法来存储和检索对象集合?

【问题讨论】:

  • 能否请您提供通用功能?
  • 提示:如何将 JSON 直接存储为字符串...!!!
  • 使用 TinyDB 你可以存储通用的任何类型的对象github.com/kcochibili/TinyDB--Android-Shared-Preferences-Turbo
  • 是的,我已经完成了。当我尝试从 getListObject(String key, Class> mClass) 获取列表时,它返回一个对象列表。我应该如何将此列表转换为我的自定义对象列表? @SuryaBondada

标签: android sharedpreferences


【解决方案1】:

没有直接的方法,只有两种间接的方法:

1.使用 GSON。

public static boolean saveObjectToPrefs(String prefKey, Object object, Context context) {
    SharedPreferences.Editor editor = getSharedPreferences(context).edit();
    try {
        Gson gson = new Gson();
        String json = gson.toJson(object);
        editor.putString(prefKey, json);
        editor.apply();
        return true;
    } catch (Exception e) {
         e.printStackTrace();
         return false;
    }
}

这里的泛型应该实现Serializable接口。

要检索对象,请创建如下方法:

public static <T> T getObjectFromPrefs(String prefKey, Class<T> type, Context context) {
    String json = getSharedPreferences(context).getString(prefKey, null);
    if (json != null) {
        try {
            Gson gson = new Gson();
            T result = gson.fromJson(json, type);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return null;
}

你可以像集合一样调用这个方法:

PrefUtils.getObjectFromPrefsByType(PREF_KEY_USERS, new TypeToken<ArrayList<User>>() {
    }.getType(), context);

对于普通对象,您可以这样做:

PrefUtils.getObjectFromPrefsByType(PREF_KEY_USER, User.class, context);

2。编写自定义序列化器和反序列化器

我通常更喜欢这种方法,因为我不必为它包含库。

这是自定义序列化器/反序列化器的实现:

public class ObjectSerializer {


public static String serialize(Serializable obj){
    if (obj == null) return "";
    try {
        ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
        ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
        objStream.writeObject(obj);
        objStream.close();
        return encodeBytes(serialObj.toByteArray());

    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }

}

public static Object deserialize(String str)  {
    if (str == null || str.length() == 0) return null;
    try {
        ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str));
        ObjectInputStream objStream = new ObjectInputStream(serialObj);
        return objStream.readObject();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

public static String encodeBytes(byte[] bytes) {
    StringBuilder strBuf = new StringBuilder();
    for (Byte b: bytes) {
        strBuf.append((char) (((b >> 4) & 0xF) + ((int) 'a')));
        strBuf.append((char) (((b) & 0xF) + ((int) 'a')));
    }
    return strBuf.toString();
}

public static byte[] decodeBytes(String str) {
    byte[] bytes = new byte[str.length() / 2];
    for (int i = 0; i < str.length(); i+=2) {
        char c = str.charAt(i);
        bytes[i/2] = (byte) ((c - 'a') << 4);
        c = str.charAt(i+1);
        bytes[i/2] += (c - 'a');
    }
    return bytes;
    }
}

现在,在 PrefUtils.java 中,您可以使用如下方法:

public static void saveUser(Context context, User user) {
    getSharedPreferences(context)
                        .edit()
                        .putString(PREF_KEY_USER, ObjectSerializer.serialize(user))
                        .apply();
}

要检索对象,您可以使用以下方法:

public static User getUser(Context context) {
    String serializedUser = getSharedPreferences(context).getString(PREF_KEY_USER, "");
    return ((User) ObjectSerializer.deserialize(serializedUser));
}

同样,用户类必须是可序列化的。另外,不要忘记显式转换,因为 ObjectSerializer.deserialize(String str) 方法返回 Object 类型的对象,而不是您序列化的类。另外,请注意空值。

【讨论】:

  • 我们如何使用这个泛型来存储和检索对象列表?@Embydextrous
  • 你说的是GSON方法吗:保存调用:PrefUtils.saveObjectToPrefs(PREF_KEY_USERS, users, context); //users 是 ArrayList 并且 User 是可序列化的。
  • 检索调用:PrefUtils.getObjectFromPrefsByType(PREF_KEY_USER, new TypeToken>() { }.getType(), context);
  • 我们可以让它更通用。比如有一个方法来存储对象列表(可以是任何自定义对象)和获取特定类型对象列表的方法。
  • @Karan.. 我认为我们这里只有单一方法。一个用于保存对象,另一个用于检索对象。唯一不同的是类型和首选项键。但是,在第二种方法的情况下,您必须使用不同的方法。没有办法使用单一的方法来做到这一点。
【解决方案2】:

是否有一种通用的方法来存储和检索对象集合?

不,到目前为止,还没有通用的方法。您可以使用以下方法:

  • putBoolean(字符串键,布尔值)

  • putFloat(字符串键,浮点值)

  • putInt(String key, int value)

  • putLong(字符串键,长值)

  • putString(字符串键,字符串值)

  • putStringSet(字符串键,设置值)

这就是SharedPreferences 所能做的一切。如果你想存储任何通用的东西,你可以尝试序列化你的对象并将它作为一个字符串放到 SharedPreferences 中。 About Serialization

【讨论】:

    【解决方案3】:

    我花了很多时间来解决这个问题。既然我和一个 iPhone 人一起工作,怎么能保存任何对象(那是什么??):)

    我已经确定了 2 个解决方案。如果我存储了一个短期使用的缓存,我会使用 Parceler (https://github.com/johncarl81/parceler) 将一个任意对象包装为 Parceable。

    如果我需要应用程序用来保存用户操作的持久数据,我会使用 GSON 包装任意对象,并将其保存到磁盘。这样我仍然可以使用更多字段更新应用程序,并且仍然使用来自 GSON 对象的数据,因为它处理空值字段。 (https://github.com/google/gson)

    【讨论】:

      猜你喜欢
      • 2011-09-29
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多