是否可以在Android上向SharedPreferences添加数组或对象

时间:2010-10-06 20:40:35

标签: android android-preferences sharedpreferences

我有ArrayList个具有名称和图标指针的对象,我想将其保存在SharedPreferences中。我该怎么办?

注意:我不想使用数据库

11 个答案:

答案 0 :(得分:69)

无论API级别如何,请检查String arrays and Object arrays in SharedPreferences


保存阵列

public boolean saveArray(String[] array, String arrayName, Context mContext) {   
    SharedPreferences prefs = mContext.getSharedPreferences("preferencename", 0);  
    SharedPreferences.Editor editor = prefs.edit();  
    editor.putInt(arrayName +"_size", array.length);  
    for(int i=0;i<array.length;i++)  
        editor.putString(arrayName + "_" + i, array[i]);  
    return editor.commit();  
} 

LOAD ARRAY

public String[] loadArray(String arrayName, Context mContext) {  
    SharedPreferences prefs = mContext.getSharedPreferences("preferencename", 0);  
    int size = prefs.getInt(arrayName + "_size", 0);  
    String array[] = new String[size];  
    for(int i=0;i<size;i++)  
        array[i] = prefs.getString(arrayName + "_" + i, null);  
    return array;  
}  

答案 1 :(得分:59)

所以来自Data Storage上的Android开发者网站:

  

用户首选项

     

共享偏好并非严格用于保存“用户首选项”,例如用户选择的铃声。如果您对为应用程序创建用户首选项感兴趣,请参阅PreferenceActivity,它为您创建用于创建用户首选项的Activity框架,该框架将自动保留(使用共享首选项)。

所以我认为这是可以的,因为它只是持久的键值对。

对于原始海报,这并不难。您只需遍历数组列表并添加项目即可。在这个例子中,我使用了一个简单的地图,但你可以使用数组列表并适当地改变它:

// my list of names, icon locations
Map<String, String> nameIcons = new HashMap<String, String>();
nameIcons.put("Noel", "/location/to/noel/icon.png");
nameIcons.put("Bob", "another/location/to/bob/icon.png");
nameIcons.put("another name", "last/location/icon.png");

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

for (String s : nameIcons.keySet()) {
    // use the name as the key, and the icon as the value
    keyValuesEditor.putString(s, nameIcons.get(s));
}
keyValuesEditor.commit()

你会做类似的事情再次读取键值对。如果有效,请告诉我。

更新:如果您使用的是API级别11或更高版本,则会有method写出字符串集

答案 2 :(得分:57)

写,

SharedPreferences prefs = PreferenceManager
        .getDefaultSharedPreferences(this);
JSONArray jsonArray = new JSONArray();
jsonArray.put(1);
jsonArray.put(2);
Editor editor = prefs.edit();
editor.putString("key", jsonArray.toString());
System.out.println(jsonArray.toString());
editor.commit();

阅读,

try {
    JSONArray jsonArray2 = new JSONArray(prefs.getString("key", "[]"));
    for (int i = 0; i < jsonArray2.length(); i++) {
         Log.d("your JSON Array", jsonArray2.getInt(i)+"");
    }
} catch (Exception e) {
    e.printStackTrace();
}

答案 3 :(得分:31)

共享偏好设置在API级别11中引入了getStringSetputStringSet方法,但这与旧版本的Android(仍然很受欢迎)不兼容,并且仅限于字符串集。< / p>

Android没有提供更好的方法,并且循环地图和数组以保存和加载它们并不是非常简单和干净,特别是对于数组。但更好的实施并不难:

package com.example.utils;

import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.content.SharedPreferences;

public class JSONSharedPreferences {
    private static final String PREFIX = "json";

    public static void saveJSONObject(Context c, String prefName, String key, JSONObject object) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(JSONSharedPreferences.PREFIX+key, object.toString());
        editor.commit();
    }

    public static void saveJSONArray(Context c, String prefName, String key, JSONArray array) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(JSONSharedPreferences.PREFIX+key, array.toString());
        editor.commit();
    }

    public static JSONObject loadJSONObject(Context c, String prefName, String key) throws JSONException {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        return new JSONObject(settings.getString(JSONSharedPreferences.PREFIX+key, "{}"));
    }

    public static JSONArray loadJSONArray(Context c, String prefName, String key) throws JSONException {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        return new JSONArray(settings.getString(JSONSharedPreferences.PREFIX+key, "[]"));
    }

    public static void remove(Context c, String prefName, String key) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        if (settings.contains(JSONSharedPreferences.PREFIX+key)) {
            SharedPreferences.Editor editor = settings.edit();
            editor.remove(JSONSharedPreferences.PREFIX+key);
            editor.commit();
        }
    }
}

现在,您可以使用这五种方法将任何集合保存在共享首选项中。使用JSONObjectJSONArray非常简单。您可以使用JSONArray (Collection copyFrom)公共构造函数从任何Java集合中生成JSONArray,并使用JSONArray的{​​{1}}方法来访问元素。

共享首选项没有大小限制(除了设备的存储限制),因此这些方法适用于您希望在应用中快速轻松地存储某些集合的大多数常见情况。但是JSON解析在这里发生,并且Android中的首选项在内部存储为XML,所以我建议在处理兆字节数据时使用其他持久数据存储机制。

答案 4 :(得分:15)

使用Gson谷歌库[1]

进行复杂对象存储的简易模式
public static void setComplexObject(Context ctx, ComplexObject obj){
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
    SharedPreferences.Editor editor = preferences.edit();
    editor.putString("COMPLEX_OBJECT",new Gson().toJson(obj)); 
    editor.commit();
}

public static ComplexObject getComplexObject (Context ctx){
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
    String sobj = preferences.getString("COMPLEX_OBJECT", "");
    if(sobj.equals(""))return null;
    else return new Gson().fromJson(sobj, ComplexObject.class);
}

[1] http://code.google.com/p/google-gson/

答案 5 :(得分:3)

我将一系列腰围尺寸(已在我的array.xml中创建)加载到我的preferences.xml文件中,其中包含以下代码。 @ array / pant_inch_size是整个数组的id。

 <ListPreference 
 android:title="choosepantsize"
 android:summary="Choose Pant Size"
 android:key="pantSizePref" 
 android:defaultValue="34" 
 android:entries="@array/pant_inch_size"
 android:entryValues="@array/pant_inch_size" /> 

这将使用数组中的选项填充菜单。我将默认大小设置为34,因此当弹出菜单时,他们会看到大小34已预先选中。

答案 6 :(得分:2)

简单的方法是,将其转换为JSON String,如下例所示:

Gson gson = new Gson();
String json = gson.toJson(myObj);

然后将字符串存储在共享首选项中。 一旦需要它,只需从共享首选项中获取字符串并转换回JSONArray或JSONObject(根据您的要求)。

答案 7 :(得分:1)

写作:

 private <T> void storeData(String key, T data) {
    ByteArrayOutputStream serializedData = new ByteArrayOutputStream();

    try {
        ObjectOutputStream serializer = new ObjectOutputStream(serializedData);
        serializer.writeObject(data);
    } catch (IOException e) {
        e.printStackTrace();
    }

    SharedPreferences sharedPreferences = getSharedPreferences(TAG, 0);
    SharedPreferences.Editor edit = sharedPreferences.edit();

    edit.putString(key, Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT));
    edit.commit();
}

阅读:

private <T> T getStoredData(String key) {
    SharedPreferences sharedPreferences = getSharedPreferences(TAG, 0);
    String serializedData = sharedPreferences.getString(key, null);
    T storedData = null;
    try {
        ByteArrayInputStream input = new ByteArrayInputStream(Base64.decode(serializedData, Base64.DEFAULT));
        ObjectInputStream inputStream = new ObjectInputStream(input);
        storedData = (T)inputStream.readObject();
    } catch (IOException|ClassNotFoundException|java.lang.IllegalArgumentException e) {
        e.printStackTrace();
    }

    return storedData;
}

答案 8 :(得分:1)

这是我成功使用的共享偏好设置代码,请参阅此link

  public class MainActivity extends Activity {

private static final int RESULT_SETTINGS = 1;
Button button;
public String a="dd";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

 button = (Button) findViewById(R.id.btnoptions);


setContentView(R.layout.activity_main);

  // showUserSettings();
  }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return true;
 }

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {

case R.id.menu_settings:
 Intent i = new Intent(this, UserSettingActivity.class);
 startActivityForResult(i, RESULT_SETTINGS);
 break;

 }

return true;
}

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data)     {
  super.onActivityResult(requestCode, resultCode, data);

 switch (requestCode) {
 case RESULT_SETTINGS:
 showUserSettings();
 break;

 } 

  }

  private void showUserSettings() {
 SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);

 StringBuilder builder = new StringBuilder();

 builder.append("\n Pet: "
  + sharedPrefs.getString("prefpetname", "NULL"));

 builder.append("\n Address:"
 + sharedPrefs.getString("prefaddress","NULL" ));

 builder.append("\n Your name: "
 + sharedPrefs.getString("prefname", "NULL"));

 TextView settingsTextView = (TextView) findViewById(R.id.textUserSettings);


  settingsTextView.setText(builder.toString());


    }

   }

快乐的编码!

答案 9 :(得分:0)

您可以使用 putStringSet

这使您可以像这样将HashSet保存在首选项中:

保存

Set<String> values;

SharedPreferences sharedPref = 
    mContext.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);

Editor editor = sharedPref.edit();

editor.putStringSet("YOUR_KEY", values);
editor.apply();

检索

SharedPreferences sharedPref = 
    mContext.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);

Editor editor = sharedPref.edit();

Set<String> newList = editor.getStringSet("YOUR_KEY", null);

putStringSet仅允许一个Set,这是一个无序列表。

答案 10 :(得分:0)

当我对此感到困惑时,我得到了序列化解决方案,您可以在其中序列化字符串,但是我也想出了一个解决办法。

仅当您尚未阅读有关序列化的内容时,请阅读此内容,否则请继续阅读我的内容

为了按顺序存储数组项,我们可以将数组序列化为单个字符串(通过创建一个新的ObjectSerializer类(从– www.androiddevcourse.com/objectserializer.html复制代码,替换除包名称))

以“共享”首选项输入数据: enter image description here

第38行的其余代码- enter image description here

按如下所示放置下一个arg,这样,如果未检索到数据,它将返回空数组(我们不能将空字符串coz放入容器/变量是不是字符串的数组)

来到我的网站:-

通过在每个项目之间添加一些符号,将数组的内容合并为单个字符串,然后在检索它时使用该符号对其进行拆分。通过共享首选项,可以轻松添加和检索String。 如果您担心拆分,请查找“在Java中拆分字符串”。

[注意:如果数组的内容是原始类型(例如字符串,整数,浮点数等),此方法将很好地工作。它将适用于具有自己结构的复杂数组,假设是电话簿,但是合并和拆分会变得有点复杂。 ]

PS:我是android的新手,所以不知道它是不是一个不错的hack,所以让我知道您是否发现了更好的hack。