【问题标题】:How to save HashMap to Shared Preferences?如何将 HashMap 保存到共享首选项?
【发布时间】:2011-12-18 04:17:53
【问题描述】:

如何在 Android 中将 HashMap 对象 保存到 Shared Preferences 中?

【问题讨论】:

标签: android sharedpreferences


【解决方案1】:

我使用GsonHashMap转换为String,然后保存到SharedPrefs

private void hashmaptest()
{
    //create test hashmap
    HashMap<String, String> testHashMap = new HashMap<String, String>();
    testHashMap.put("key1", "value1");
    testHashMap.put("key2", "value2");

    //convert to string using gson
    Gson gson = new Gson();
    String hashMapString = gson.toJson(testHashMap);

    //save in shared prefs
    SharedPreferences prefs = getSharedPreferences("test", MODE_PRIVATE);
    prefs.edit().putString("hashString", hashMapString).apply();

    //get from shared prefs
    String storedHashMapString = prefs.getString("hashString", "oopsDintWork");
    java.lang.reflect.Type type = new TypeToken<HashMap<String, String>>(){}.getType();
    HashMap<String, String> testHashMap2 = gson.fromJson(storedHashMapString, type);

    //use values
    String toastString = testHashMap2.get("key1") + " | " + testHashMap2.get("key2");
    Toast.makeText(this, toastString, Toast.LENGTH_LONG).show();
}

【讨论】:

  • how to get hashmap from gson i got error msg like com.qb.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 –
  • 预期 BEGIN_OBJECT 但 BEGIN_ARRAY 正在发生,因为 HashMap 应该是 HashMap,如果值始终是 String 对象,则不会有任何问题,但如果某些值键是 diff 然后是字符串(例如自定义对象,或列表或数组),然后将抛出异常。因此,为了能够解析您需要的所有内容 HashMap
【解决方案2】:

我不建议将复杂对象写入 SharedPreference。相反,我会使用ObjectOutputStream 将其写入内部存储器。

File file = new File(getDir("data", MODE_PRIVATE), "map");    
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
outputStream.writeObject(map);
outputStream.flush();
outputStream.close();

【讨论】:

  • 使用 ObjectInputStream。
  • 这里是一个如何一起使用 ObjectOutputStream 和 ObjectInputStream 的例子:tutorialspoint.com/java/io/objectinputstream_readobject.htm
  • Hashmap什么时候是复杂对象了?你是怎么假设的?
  • 为什么不建议将 HashMap 之类的对象放入 SharedPreference 中?
  • 当您写入 sharedpreferences 时,您会保存键值数据,因此它与保存 hashmap 并没有太大区别
【解决方案3】:
private void saveMap(Map<String,Boolean> inputMap) {
    SharedPreferences pSharedPref = getApplicationContext().getSharedPreferences("MyVariables", Context.MODE_PRIVATE);
    if (pSharedPref != null){
        JSONObject jsonObject = new JSONObject(inputMap);
        String jsonString = jsonObject.toString();
        pSharedPref.edit()
            .remove("My_map")
            .putString("My_map", jsonString)
            .apply();
    }
}

private Map<String,Boolean> loadMap() {
    Map<String,Boolean> outputMap = new HashMap<>();
    SharedPreferences pSharedPref = getApplicationContext().getSharedPreferences("MyVariables", Context.MODE_PRIVATE);
    try {
        if (pSharedPref != null) {
            String jsonString = pSharedPref.getString("My_map", (new JSONObject()).toString());
            if (jsonString != null) {
                JSONObject jsonObject = new JSONObject(jsonString);
                Iterator<String> keysItr = jsonObject.keys();
                while (keysItr.hasNext()) {
                    String key = keysItr.next();
                    Boolean value = jsonObject.getBoolean(key); 
                    outputMap.put(key, value);
                }
            }
        }
    } catch (JSONException e){
        e.printStackTrace();
    }
    return outputMap;
}

【讨论】:

  • 完美答案:)
  • 如何从一个简单的类中访问getApplicationContext
  • @Dmitry 一个快捷方式:在你的简单类中,包含设置上下文方法并将上下文设置为成员变量并相应地使用它
  • getString() 的奇怪复杂的默认值有什么意义?一个简单的 null 或空字符串不是也能正常工作吗?
  • 这段代码很糟糕:1)你捕获了一个通用异常而不是一个 json 异常。为什么需要泛型?由于您可能有 NPE,您可以通过检查 json 字符串的 null 来避免这种情况(您已经为共享首选项执行此操作)。
【解决方案4】:
Map<String, String> aMap = new HashMap<String, String>();
aMap.put("key1", "val1");
aMap.put("key2", "val2");
aMap.put("Key3", "val3");

SharedPreferences keyValues = getContext().getSharedPreferences("Your_Shared_Prefs"), Context.MODE_PRIVATE);
SharedPreferences.Editor keyValuesEditor = keyValues.edit();

for (String s : aMap.keySet()) {
    keyValuesEditor.putString(s, aMap.get(s));
}

keyValuesEditor.commit();

【讨论】:

  • 但我需要像我们将向量添加到共享首选项中一样将哈希映射保存为自身
  • 你可能不得不使用序列化并将序列化的 HashMap 保存在 SharedPrefs 中。您可以轻松找到有关如何执行此操作的代码示例。
【解决方案5】:

作为 Vinoj John Hosan 答案的衍生,我修改了答案以允许更通用的插入,基于数据的键,而不是像 "My_map" 这样的单个键。

在我的实现中,MyApp 是我的 Application 覆盖类,MyApp.getInstance() 用于返回 context

public static final String USERDATA = "MyVariables";

private static void saveMap(String key, Map<String,String> inputMap){
    SharedPreferences pSharedPref = MyApp.getInstance().getSharedPreferences(USERDATA, Context.MODE_PRIVATE);
    if (pSharedPref != null){
        JSONObject jsonObject = new JSONObject(inputMap);
        String jsonString = jsonObject.toString();
        SharedPreferences.Editor editor = pSharedPref.edit();
        editor.remove(key).commit();
        editor.putString(key, jsonString);
        editor.commit();
    }
}

private static Map<String,String> loadMap(String key){
    Map<String,String> outputMap = new HashMap<String,String>();
    SharedPreferences pSharedPref = MyApp.getInstance().getSharedPreferences(USERDATA, Context.MODE_PRIVATE);
    try{
        if (pSharedPref != null){
            String jsonString = pSharedPref.getString(key, (new JSONObject()).toString());
            JSONObject jsonObject = new JSONObject(jsonString);
            Iterator<String> keysItr = jsonObject.keys();
            while(keysItr.hasNext()) {
                String k = keysItr.next();
                String v = (String) jsonObject.get(k);
                outputMap.put(k,v);
            }
        }
    }catch(Exception e){
        e.printStackTrace();
    }
    return outputMap;
}

【讨论】:

【解决方案6】:

地图 -> 字符串

val jsonString: String  = Gson().toJson(map)
preferences.edit().putString("KEY_MAP_SAVE", jsonString).apply()

字符串 -> 地图

val jsonString: String = preferences.getString("KEY_MAP_SAVE", JSONObject().toString())
val listType = object : TypeToken<Map<String, String>>() {}.type
return Gson().fromJson(jsonString, listType)

【讨论】:

    【解决方案7】:

    您可以尝试使用 JSON。

    为了节省

    try {
        HashMap<Integer, String> hash = new HashMap<>();
        JSONArray arr = new JSONArray();
        for(Integer index : hash.keySet()) {
            JSONObject json = new JSONObject();
            json.put("id", index);
            json.put("name", hash.get(index));
            arr.put(json);
        }
        getSharedPreferences(INSERT_YOUR_PREF).edit().putString("savedData", arr.toString()).apply();
    } catch (JSONException exception) {
        // Do something with exception
    }
    

    为了得到

    try {
        String data = getSharedPreferences(INSERT_YOUR_PREF).getString("savedData");
        HashMap<Integer, String> hash = new HashMap<>();
        JSONArray arr = new JSONArray(data);
        for(int i = 0; i < arr.length(); i++) {
            JSONObject json = arr.getJSONObject(i);
            hash.put(json.getInt("id"), json.getString("name"));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    

    【讨论】:

      【解决方案8】:

      您可以在专用的共享首选项文件中使用它(来源:https://developer.android.com/reference/android/content/SharedPreferences.html):

      全部获取

      在 API 级别 1 中添加了 Map getAll () 从以下位置检索所有值 偏好。

      注意,不能修改此方法返回的集合, 或更改其任何内容。您存储的数据的一致性是 不保证会这样做。

      返回 Map 返回包含对列表的映射 表示偏好的键/值。

      【讨论】:

      • 我认为这实际上是一个更好更简单的想法。您只需为此地图创建一个专用的 SharedPreferences,除了从/到实际数据类型的额外转换之外,您还可以继续使用。
      【解决方案9】:
      String converted = new Gson().toJson(map);
      SharedPreferences sharedPreferences = getSharedPreferences("sharepref",Context.MODE_PRIVATE);
      sharedPreferences.edit().putString("yourkey",converted).commit();
      

      【讨论】:

      • 如何返回地图?
      【解决方案10】:

      懒惰的方式:将每个键直接存储在 SharedPreferences 中

      对于狭窄的用例,当您的地图只有不超过几十个元素时,您可以利用 SharedPreferences 的工作方式与地图非常相似的事实,只需将每个条目存储在自己的键下:

      存储地图

      Map<String, String> map = new HashMap<String, String>();
      map.put("color", "red");
      map.put("type", "fruit");
      map.put("name", "Dinsdale");
      
      
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
      // OR use a specific pref name
      // context.getSharedPreferences("myMegaMap");
      
      for (Map.Entry<String, String> entry : map.entrySet()) {
          prefs.edit().putString(entry.getKey(), entry.getValue());
      }
      

      从地图中读取键

      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
      // OR use a specific pref name
      // context.getSharedPreferences("myMegaMap");
      prefs.getString("color", "pampa");
      

      如果您使用自定义首选项名称(即context.getSharedPreferences("myMegaMap")),您还可以使用prefs.getAll() 获取所有键

      您的值可以是 SharedPreferences 支持的任何类型:Stringintlongfloatboolean

      【讨论】:

        【解决方案11】:

        使用File Stream

        fun saveMap(inputMap: Map<Any, Any>, context: Context) {
            val fos: FileOutputStream = context.openFileOutput("map", Context.MODE_PRIVATE)
            val os = ObjectOutputStream(fos)
            os.writeObject(inputMap)
            os.close()
            fos.close()
        }
        
        fun loadMap(context: Context): MutableMap<Any, Any> {
            return try {
                val fos: FileInputStream = context.openFileInput("map")
                val os = ObjectInputStream(fos)
                val map: MutableMap<Any, Any> = os.readObject() as MutableMap<Any, Any>
                os.close()
                fos.close()
                map
            } catch (e: Exception) {
                mutableMapOf()
            }
        }
        
        fun deleteMap(context: Context): Boolean {
            val file: File = context.getFileStreamPath("map")
            return file.delete()
        }
        

        用法示例:

        var exampleMap: MutableMap<Any, Any> = mutableMapOf()
        exampleMap["2"] = 1
        saveMap(exampleMap, applicationContext) //save map
        
        exampleMap = loadMap(applicationContext) //load map
        

        【讨论】:

          【解决方案12】:

          您不需要像其他人建议的那样将 HashMap 保存到文件中。保存 HashMap 和 SharedPreference 并在需要时从 SharedPreference 加载它非常容易。方法如下:
          假设你有一个

          class T
          

          你的哈希图是:

          HashMap<String, T>
          

          转换成字符串后保存如下:

                 SharedPreferences sharedPref = getSharedPreferences(
                      "MyPreference", Context.MODE_PRIVATE);
              SharedPreferences.Editor editor = sharedPref.edit();
              editor.putString("MyHashMap", new Gson().toJson(mUsageStatsMap));
              editor.apply();
          

          其中mUsageStatsMap定义为:

          HashMap<String, T>
           
          

          以下代码将从保存的共享首选项中读取哈希映射并正确加载回mUsageStatsMap

          Gson gson = new Gson();
          String json = sharedPref.getString("MyHashMap", "");
          Type typeMyType = new TypeToken<HashMap<String, UsageStats>>(){}.getType();
          HashMap<String, UsageStats> usageStatsMap = gson.fromJson(json, typeMyType);
          mUsageStatsMap = usageStatsMap;  
          

          密钥在 Type typeMyType 中,在 * gson.fromJson(json, typeMyType)* 调用中使用。它使得在 Java 中正确加载哈希映射实例成为可能。

          【讨论】:

            【解决方案13】:

            我知道这有点太晚了,但我希望这对任何阅读者都有帮助..

            所以我要做的是

            1) 创建HashMap并添加数据 喜欢:-

            HashMap hashmapobj = new HashMap();
              hashmapobj.put(1001, "I");
              hashmapobj.put(1002, "Love");
              hashmapobj.put(1003, "Java");
            

            2) 将其写入 shareprefrences 编辑器 喜欢:-

            SharedPreferences sharedpreferences = getSharedPreferences(MyPREFERENCES,Context.MODE_PRIVATE);
                Editor editor = sharedpreferences.edit();
                editor.putStringSet("key", hashmapobj );
                editor.apply(); //Note: use commit if u wan to receive response from shp
            

            3) 读取数据,例如:- 在您希望阅读的新课程中

               HashMap hashmapobj_RECIVE = new HashMap();
                 SharedPreferences sharedPreferences (MyPREFERENCES,Context.MODE_PRIVATE;
                 //reading HashMap  from sharedPreferences to new empty HashMap  object
                 hashmapobj_RECIVE = sharedpreferences.getStringSet("key", null);
            

            【讨论】:

            • 地图不是集合
            猜你喜欢
            • 2021-05-31
            • 2022-01-15
            • 2014-01-11
            • 1970-01-01
            • 1970-01-01
            • 2017-07-02
            • 2017-01-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多