如何在 SharedPreferences 中存储键值对?

How to store key value pairs in SharedPreferences?

我正在开发一个随机生成密码的应用程序。我正在添加 "save" 功能,以便用户可以将他们的密码保存在 SharedPreferences 中。 (这不是您应该对密码执行的操作)

我有一个名为 PasswordActivity 的 activity,在那个 activity 中我显示了保存的密码。

我是这样保存密码的:我提示用户输入一个 name/key 的东西作为密码,以便 he/she 以后可以识别它。然后我在实用程序 class:

中使用以下方法将密钥和密码保存在 SharedPreferences 中
public static int savePassword (Context c, String passwordKey, String passwordValue) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences (c);
    Set<String> keys = prefs.getStringSet (PASSWORD_KEYS, new HashSet<String> ());
    Set<String> values = prefs.getStringSet (PASSWORD_VALUES, new HashSet<String> ());
    SharedPreferences.Editor editor = prefs.edit ();

    boolean duplicateKey = !keys.add (passwordKey);
    boolean duplicateValue = !values.add (passwordValue);

    if (duplicateKey)
        return KEY_DUPLICATE;
    if (duplicateValue)
        return VALUE_DUPLICATE;

    editor.putStringSet (PASSWORD_KEYS, keys).
            putStringSet (PASSWORD_VALUES, values).apply ();

    return SUCCESS;
}

我写了另一个方法来获取密码和他们的名字。正如您可能已经猜到的那样,方法 return 是 HashMap<String, String>

public static HashMap<String, String> getPasswords (Context c) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences (c);
    Set<String> keys = prefs.getStringSet (PASSWORD_KEYS, new HashSet<String> ());
    Set<String> values = prefs.getStringSet (PASSWORD_VALUES, new HashSet<String> ());

    ArrayList<String> keysList = new ArrayList<> ();
    ArrayList<String> valuesList = new ArrayList<> ();

    for (String key : keys) {
        keysList.add (key);
    }

    for (String value : values) {
        valuesList.add (value);
    }

    HashMap<String, String> map = new HashMap<> ();

    for (int i = 0 ; i < keys.size () ; i++) {
        map.put (keysList.get (i), valuesList.get (i));
    }

    return map;
}

我承认代码很乱。我先把两个set里的东西都弄成ArrayLists然后把array列表里的东西加到map和return.

呸!工作量很大!

现在当用户生成密码并保存时,两组包含正确的东西:(这些是假数据)

keys:
key1

values:
value1

一切都很好。但是当我生成另一个密码并保存时,两组就变得乱七八糟了:

keys:
key1
key2

values:
value2
value1

现在当我调用 getPasswords 方法时,它会 return

{key1, value2}, {key2, value1}

这是不正确的。查看文档后,我发现:

It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.

我猜这是导致错误结果的原因。

所以我想知道是否有其他方法来存储这些密码及其名称?

我会推荐一个数据库,例如SQLCipher for Android,这样用户就可以为应用程序提供主密码,并且所有数据都加密存储在设备上。

但是,让我们假设,为了成功击退外星人入侵并防止无数人类被大规模屠杀,你必须使用SharedPreferences来实现它。之后,你将需要与机智的同伴一起乘坐被征用的外星飞船,并成功将你的应用程序上传到其中一艘外星母舰的计算机系统中(幸运的是,它恰好是 运行 Android,因为 Android 在整个银河系拥有显着的市场份额)。

任一:

  1. 让每个键和值在 SharedPreferences 中成为单独的条目。毕竟,SharedPreferences 键值存储。为您的键和值使用专用的首选项文件(以免与您可能想要存储的任何其他内容发生冲突),然后您就知道所有的键都是来自用户的。

  2. HashMap 编组为 JSON 或 XML 或其他内容并将其保存为字符串,根据需要解组。

由于您要存储多个名称和密码,我建议使用本地 SQLite 数据库。 SharedPreferences 适用于单个值,而不是值集。

如果您不想设置整个 SQLiteOpenHelper 和所有原始 SQL 代码,您可以看看一些 ORM 助手,例如 SugarOrm(我目前使用这个, 它非常容易设置和使用)