Чи можна додати масив або об'єкт до SharedPreferences на Android


83

У мене є ArrayListоб'єкти, що мають ім'я та вказівник на піктограму, і я хочу зберегти їх у SharedPreferences. Як я можу зробити?

ПРИМІТКА: Я не хочу використовувати базу даних

Відповіді:


60

Отже, з веб-сайту розробника Android щодо зберігання даних :

Налаштування користувача

Спільні налаштування не є суто для збереження "користувацьких уподобань", таких як те, який сигнал дзвінка вибрав користувач. Якщо ви зацікавлені у створенні користувацьких уподобань для вашого додатка, див.

Тому я думаю, що це нормально, оскільки це просто просто пари ключ-значення, які зберігаються.

Для оригінального плаката це не так складно. Ви просто переглядаєте список масивів і додаєте елементи. У цьому прикладі я використовую карту для простоти, але ви можете використовувати список масивів і правильно його змінити:

// 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 або пізнішого, існує спосіб виписати набір рядків


Дякую Ноелю, я зрозумів це за допомогою вашого коду. Хоча стежте за помилками коду. ;)
zsniperx

Працював як шарм ... Thx
Бала Вішну

74

Незалежно від рівня API, перевірте масиви рядків та масиви об’єктів у 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();  
} 

МАСИВА ЗАГРУЗКИ

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;  
}  

10
Це жахлива техніка. Дивіться коментарі до цього блогу: "Проблема цього підходу полягає в тому, що ви забруднюєте свої уподобання. Скажімо, ви зберігаєте масив із 100 записами, а потім стискаєте його до пункту 2. Ви все одно матимете 100 записів у своїх уподобаннях, якщо ви не спочатку приберіть ".
Kyle Ivey

2
Прибирання є досить простим доповненням
Шериф ель-Хатіб,

Дякую, дуже приємний стиль коду. Це одна з моїх улюблених відповідей тут, на SO. :)
Мартін Пфеффер,

3
Це неправильний підхід !!! ви спробуєте додати 100 змінних, і це жахливо !! замість цього ви можете використовувати цей метод з jsonarray і jsonbj: stackoverflow.com/a/8287418/2652368
Амір Хоссейн Гасемі

@AmirHosseinGhasemi обидва підходи насправді є хаками. спасибі
Шериф ель-Хатіб

60

Писати,

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();
}

31

Спільні уподобання представили a getStringSetта putStringSetметоди на рівні API 11, але це не сумісно зі старими версіями Android (які все ще популярні), а також обмежено наборами рядків.

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();
        }
    }
}

Тепер ви можете зберегти будь-яку колекцію у спільних налаштуваннях за допомогою цих п’яти методів. Працювати JSONObjectі JSONArrayдуже просто. Ви можете використовувати JSONArray (Collection copyFrom)публічний конструктор, щоб створити JSONArrayбудь-яку колекцію Java та використовувати методи JSONArray'' getдля доступу до елементів.

Немає обмежень розміру для спільних налаштувань (крім обмежень пам’яті пристрою), тому ці методи можуть працювати в більшості звичайних випадків, коли ви хочете швидко і просто зберігати деяку колекцію у своєму додатку. Але аналіз JSON відбувається тут, і налаштування в Android зберігаються як XML всередині, тому я рекомендую використовувати інші постійні механізми зберігання даних, коли ви маєте справу з мегабайтами даних.


7
Якщо ви використовуєте JSON, можливо, перевірте gson: code.google.com/p/google-gson - він перетворює об'єкти Java у JSON і з нього.
FeatureCreep

Це було б цікаве поєднання.
Мостафа

17

Простий режим для зберігання складних об’єктів за допомогою бібліотеки Google 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/


Найкращий! Позначте це як ВІДПОВІДЬ!
Renan Franca

3

Я завантажив масив розмірів талії (вже створений у моєму масиві array.xml) у файл preferences.xml із кодом нижче. @ array / pant_inch_size - це ідентифікатор усього масиву.

 <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 був попередньо вибраний.


Привіт Кіт, дякую за вашу відповідь. Мені потрібно зберегти замовлення, і я не працюю з користувацьким інтерфейсом, тому я не зважаю, що ваш код збігається з тим, що мені потрібно виконати. Спасибі в будь-якому випадку
zsniperx

ах !! Я неправильно витлумачив ваше запитання, вибачте за це. Для будь-яких інших читачів мій XML-код просто захоплює елементи з мого файлу array.xml та завантажує їх у меню налаштувань, у цьому випадку за замовчуванням вибрано "34". Потім я використовую java, щоб знайти ідентифікатор для цієї конкретної переваги, який є "pantSizePref" ("ключ").
Кіт,

2

Найпростіший спосіб - перетворити його на JSON String, як показано нижче:

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

Потім збережіть рядок у спільних налаштуваннях. Як тільки він вам знадобиться, просто отримайте рядок із загальних налаштувань і перетворіть назад у JSONArray або JSONObject (відповідно до ваших вимог.)


2

Для написання:

 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;
}

Це здається здоровою пропозицією. Усі загальні колекції реалізують Serializable, а ваші основні String, Number і Date - Serializable. Єдиним мінусом буде продуктивність.
androidguy

1

Це код спільних налаштувань, який я успішно використовую. Перейдіть за цим посиланням :

  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());


    }

   }

ЩИРОГО КОДУВАННЯ!


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, і це невпорядкований список.


0

Коли мене з цим прослуховували, я отримав рішення для серіалізації, де ви можете серіалізувати свій рядок, але я також придумав хак.

Читайте це, лише якщо ви ще не читали про серіалізацію, інакше спуститесь і прочитайте мій хак

Для того, щоб зберігати елементи масиву в порядку, ми можемо серіалізувати масив в один рядок (створивши новий клас ObjectSerializer (скопіюйте код з - www.androiddevcourse.com/objectserializer.html, замініть все, крім імені пакета))

Введення даних у Спільні налаштування: введіть тут опис зображення

решта коду в рядку 38 - введіть тут опис зображення

Поставте наступний аргумент як такий, щоб, якщо дані не отримано, він повернув порожній масив (ми не можемо помістити порожній рядок, оскільки контейнер / змінна є масивом, а не рядком)

До мого зламу: -

Об’єднайте вміст масиву в один рядок, маючи якийсь символ між кожним елементом, а потім розділіть його, використовуючи цей символ під час отримання. Coz додавання та отримання рядка легко за допомогою спільних налаштувань. Якщо ви стурбовані розділенням, просто шукайте "розділення рядка в Java".

[Примітка: Це чудово працює, якщо вміст вашого масиву примітивного типу, як рядок, int, float тощо. Це буде працювати для складних масивів, які мають власну структуру, припустимо телефонну книгу, але злиття та розбиття стане трохи складний. ]

PS: Я новачок в android, тому не знаю, чи це хороший хак, тому lemme знає, чи знайдете ви кращі хаки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.