【问题标题】:How can I store an integer array in SharedPreferences?如何在 SharedPreferences 中存储整数数组?
【发布时间】:2011-11-02 19:16:36
【问题描述】:

我想使用 SharedPreferences 保存/调用一个整数数组,这可能吗?

【问题讨论】:

    标签: android sharedpreferences


    【解决方案1】:

    您只能将原始值保存在 sharedPreference 中。请改用Sqlite

    【讨论】:

      【解决方案2】:

      您不能将数组放在 SharedPreferences 中,但您可以解决方法:

      private static final String LEN_PREFIX = "Count_";
      private static final String VAL_PREFIX = "IntValue_";
      public void storeIntArray(String name, int[] array){
          SharedPreferences.Editor edit= mContext.getSharedPreferences("NAME", Context.MODE_PRIVATE).edit();
          edit.putInt(LEN_PREFIX + name, array.length);
          int count = 0;
          for (int i: array){
              edit.putInt(VAL_PREFIX + name + count++, i);
          }
          edit.commit();
      }
      public int[] getFromPrefs(String name){
          int[] ret;
          SharedPreferences prefs = mContext.getSharedPreferences("NAME", Context.MODE_PRIVATE);
          int count = prefs.getInt(LEN_PREFIX + name, 0);
          ret = new int[count];
          for (int i = 0; i < count; i++){
              ret[i] = prefs.getInt(VAL_PREFIX+ name + i, i);
          }
          return ret;
      }
      

      【讨论】:

        【解决方案3】:

        你可以尝试这样做:

        • 将你的整数放入一个字符串中,用一个字符(例如逗号)分隔每个 int,然后将它们保存为字符串:

          SharedPreferences prefs = getPreferences(MODE_PRIVATE);
          int[] list = new int[10];
          StringBuilder str = new StringBuilder();
          for (int i = 0; i < list.length; i++) {
              str.append(list[i]).append(",");
          }
          prefs.edit().putString("string", str.toString());
          
        • 获取字符串并使用 StringTokenizer 解析它:

          String savedString = prefs.getString("string", "");
          StringTokenizer st = new StringTokenizer(savedString, ",");
          int[] savedList = new int[10];
          for (int i = 0; i < 10; i++) {
              savedList[i] = Integer.parseInt(st.nextToken());
          }
          

        【讨论】:

        【解决方案4】:

        这是我的版本,基于 Egor 的回答。我不喜欢使用 StringBuilder ,除非我正在构建一个巨大的字符串,但是感谢 Egor 使用 StringTokenizer ——过去没有太多使用它,但它非常方便!仅供参考,这在我的实用程序类中:

        public static void saveIntListPrefs(
            String name, Activity activity, List<Integer> list)
        {
          String s = "";
          for (Integer i : list) {
            s += i + ",";
          }
        
          Editor editor = activity.getPreferences(Context.MODE_PRIVATE).edit();
          editor.putString(name, s);
          editor.commit();
        }
        
        public static ArrayList<Integer> readIntArrayPrefs(String name, Activity activity)
        {
          SharedPreferences prefs = activity.getPreferences(Context.MODE_PRIVATE);
          String s = prefs.getString(name, "");
          StringTokenizer st = new StringTokenizer(s, ",");
          ArrayList<Integer> result = new ArrayList<Integer>();
          while (st.hasMoreTokens()) {
            result.add(Integer.parseInt(st.nextToken()));
          }
          return result;
        }
        

        【讨论】:

        • for 循环应该使用 StringBuilder 类,并且没有这样的字符串连接。
        【解决方案5】:

        两种解决方案:

        (1) 使用http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html

        它具有拆分/连接功能,可让您将整数连接和拆分为一个内衬:

        StringUtils.join([1, 2, 3], ';')  = "1;2;3"
        StringUtils.split("1;2;3", ';')   = ["1", "2", "3"]
        

        不过,您仍然需要将字符串转换回整数。

        实际上,拆分java.lang.String.split() 也可以正常工作: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String)

        (2) 使用 SharedPreferences.putStringSet() (API 11):

            SharedPreferences.Editor editor = preferences.edit();
            int count = this.intSet.size();
            if (count > 0) {
                Set<String> theSet = new HashSet<String>();
                for (Long l : this.intSet) {
                    theSet.add(String.valueOf(l));
                }
                editor.putStringSet(PREFS_KEY, theSet);
            } else {
                editor.remove(PREFS_KEY);
            }
            editor.commit();
        

        然后把它拿回来:

            Set<String> theSet = this.preferences.getStringSet(PREFS_KEY, null);
            if (theSet != null && !theSet.isEmpty()) {
                this.intSet.clear();
                for (String s : theSet) {
                    this.intSet.add(Integer.valueOf(s));
                }
            }
        

        此代码不会捕获 NPE 或 NumberFormatExceptions,因为否则会确保 intSet 不包含任何空值。但是当然,如​​果你不能保证在你的代码中你应该用 try/catch 包围它。

        【讨论】:

        • 解决方案 2 是要走的路
        • 第二种解决方案很好,但它会丢失元素顺序。
        • @blackwolf 试试java.util.SortedSet - 也许Android 正确序列化它。
        • 'SharedPreferences' 使用'HashSets'。请参阅 CommonsWare answer
        【解决方案6】:

        我喜欢使用可以作为字符串存储和检索的 JSON 来表示 SharedPreferences 中的任何复杂数据。 所以,在int数组的情况下:

        public void setPrefIntArray(String tag, int[] value)
        {
            SharedPreferences.Editor prefEditor = PreferenceManager.getDefaultSharedPreferences(context)
                    .edit();
        
            String s;
            try
            {
                JSONArray jsonArr = new JSONArray();
                for (int i : value)
                    jsonArr.put(i);
        
                JSONObject json = new JSONObject();
                json.put(tag, jsonArr);
        
                s = json.toString();
            }
            catch(JSONException excp)
            {
                s = "";
            }
        
            prefEditor.putString(tag, s);
            prefEditor.commit();
        }
        
        public int[] getPrefIntArray(String tag, int[] defaultValue)
        {
            SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        
            String s = pref.getString(tag, "");
        
            try
            {
                JSONObject json = new JSONObject(new JSONTokener(s));
                JSONArray jsonArr = json.getJSONArray(tag);
        
                int[] result = new int[jsonArr.length()];
        
                for (int i = 0; i < jsonArr.length(); i++)
                    result[i] = jsonArr.getInt(i);
        
                return result;
            }
            catch(JSONException excp)
            {
                return defaultValue;
            }
        }
        

        美妙之处在于,同样的想法可以应用于任何其他可表示为 JSON 的复杂数据。

        【讨论】:

        • 这是迄今为止最好和最通用的解决方案。您可以将这些方法设为静态(只需将上下文或 SharedPreferences / Editor 传递给函数)并将 ir 放入 Utils 类中以在任何地方使用它。
        【解决方案7】:

        这是“转换为逗号分隔的字符串”解决方案在 Kotlin 中的样子,作为扩展函数实现:

        fun SharedPreferences.Editor.putIntArray(key: String, value: IntArray): SharedPreferences.Editor {
            return putString(key, value.joinToString(
                    separator = ",", 
                    transform = { it.toString() }))
        }
        
        fun SharedPreferences.getIntArray(key: String): IntArray {
            with(getString(key, "")) {
                with(if(isNotEmpty()) split(',') else return intArrayOf()) {
                    return IntArray(count(), { this[it].toInt() })
                }
            }
        }
        

        这样您就可以像使用其他 put 和 set 方法一样使用 putIntArray(String, IntArray)getIntArray(String)

        val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        prefs.edit().putIntArray(INT_ARRAY_TEST_KEY, intArrayOf(1, 2, 3)).apply()
        val intArray = prefs.getIntArray(INT_ARRAY_TEST_KEY)
        

        【讨论】:

          猜你喜欢
          • 2017-03-03
          • 2012-05-06
          • 2014-02-21
          • 2012-02-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-29
          • 2014-05-23
          相关资源
          最近更新 更多