Czy można dodać tablicę lub obiekt do SharedPreferences w systemie Android

83

Mam ArrayListobiekt, który ma nazwę i wskaźnik ikony i chcę go zapisać SharedPreferences. Jak mam to zrobić?

UWAGA: nie chcę korzystać z bazy danych

zsniperx
źródło

Odpowiedzi:

60

A więc z witryny programistów Androida na temat przechowywania danych :

Preferencje użytkownika

Preferencje wspólne nie służą wyłącznie do zapisywania „preferencji użytkownika”, takich jak wybrany dzwonek. Jeśli jesteś zainteresowany tworzeniem preferencji użytkownika dla swojej aplikacji, zobacz PreferenceActivity, który zapewnia strukturę działania umożliwiającą tworzenie preferencji użytkownika, które zostaną automatycznie utrwalone (przy użyciu preferencji współdzielonych).

Myślę więc, że jest to w porządku, ponieważ są to po prostu pary klucz-wartość, które są utrwalane.

Dla oryginalnego plakatu nie jest to takie trudne. Po prostu przeglądasz listę tablic i dodajesz elementy. W tym przykładzie używam mapy dla uproszczenia, ale możesz użyć listy tablic i odpowiednio ją zmienić:

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

Zrobiłbyś coś podobnego, aby ponownie odczytać pary klucz-wartość. Daj mi znać, czy to działa.

Aktualizacja: jeśli używasz poziomu interfejsu API 11 lub nowszego, istnieje metoda zapisywania zestawu ciągów

kolęda
źródło
Dzięki Noel, rozgryzłem to z pomocą twojego kodu. Uważaj jednak na literówki w kodzie. ;)
zsniperx
Działał jak urok ... Thx
Bala Vishnu
74

Niezależnie od poziomu interfejsu API, sprawdź tablice ciągów i tablice obiektów w SharedPreferences


ZAPISZ ARRAY

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;  
}  
Sherif elKhatib
źródło
10
To straszna technika. Zobacz komentarze na tym blogu: „Problem z tym podejściem polega na tym, że zaśmiecasz swoje preferencje. Powiedzmy, że zapisujesz tablicę ze 100 wpisami, a następnie zmniejszasz ją do 2. Nadal będziesz mieć 100 wpisów w swoich preferencjach, chyba że wyczyść to najpierw ”.
Kyle Ivey
2
Sprzątanie jest raczej łatwym dodatkiem
Sherif elKhatib,
Dzięki, bardzo ładny stylizowany kod. To jedna z moich ulubionych odpowiedzi na SO. :)
Martin Pfeffer
3
To jest złe podejście !!! próbujesz dodać 100 zmiennych i to jest okropne !! zamiast tego możesz użyć tej metody z jsonarray i jsonbj: stackoverflow.com/a/8287418/2652368
Amir Hossein Ghasemi
@AmirHosseinGhasemi oba podejścia to w rzeczywistości hacki. dzięki
Sherif elKhatib
60

Pisać,

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

Czytać,

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();
}
Rohit
źródło
31

Wspólne preferencje wprowadziły metody a getStringSeti putStringSetw API Level 11, ale nie jest to zgodne ze starszymi wersjami systemu Android (które są nadal popularne), a także ogranicza się do zestawów ciągów.

Android nie zapewnia lepszych metod, a zapętlanie map i tablic w celu ich zapisywania i ładowania nie jest łatwe i czyste, szczególnie w przypadku tablic. Ale lepsza implementacja nie jest taka trudna:

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

Teraz możesz zapisać dowolną kolekcję we wspólnych preferencjach za pomocą tych pięciu metod. Praca z JSONObjecti JSONArrayjest bardzo łatwa. Można użyć JSONArray (Collection copyFrom)konstruktora publicznego zrobić JSONArrayz jakiegokolwiek gromadzenia i wykorzystywania Java JSONArray„s getmetody dostępu do elementów.

Nie ma limitu rozmiaru dla wspólnych preferencji (poza limitami pamięci urządzenia), więc te metody mogą działać w większości typowych przypadków, w których potrzebujesz szybkiego i łatwego przechowywania niektórych kolekcji w swojej aplikacji. Ale tutaj odbywa się parsowanie JSON, a preferencje w Androidzie są wewnętrznie przechowywane jako XML, więc zalecam używanie innych trwałych mechanizmów przechowywania danych, gdy masz do czynienia z megabajtami danych.

Mostafa
źródło
7
Jeśli wybierasz się z JSON, może sprawdź gson: code.google.com/p/google-gson - konwertuje obiekty java do iz JSON.
FeatureCreep
To byłaby interesująca kombinacja.
Mostafa
17

Łatwy tryb do przechowywania złożonych obiektów z wykorzystaniem biblioteki 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/

Hpsaturn
źródło
Najlepszy! Oznacz to jako ODPOWIEDŹ!
Renan Franca
3

Załadowałem tablicę rozmiarów talii (już utworzoną w moim array.xml) do mojego pliku preferencji.xml za pomocą poniższego kodu. @ array / pant_inch_size to identyfikator całej tablicy.

 <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" /> 

To zapełniło menu opcjami z tablicy. Ustawiam domyślny rozmiar na 34, więc kiedy wyskakuje menu, widzą, że rozmiar 34 jest wstępnie wybrany.

Keith
źródło
Cześć Keith, dziękuję za twoją odpowiedź. Muszę zapisać zamówienie i nie pracuję z preferencyjnym interfejsem użytkownika, więc nie zgadzam się, że Twój kod pasuje do tego, co muszę osiągnąć. Dzięki tak czy inaczej
zsniperx
ach !! Źle zinterpretowałem twoje pytanie, przepraszam za to. Dla innych czytelników mój kod XML po prostu pobiera elementy z mojego pliku array.xml i ładuje je do menu preferencji, z domyślną preferencją wybraną w tym przypadku jako „34”. Następnie używam języka Java, aby znaleźć identyfikator dla tej konkretnej preferencji, którym jest „pantSizePref” („klucz”).
Keith
2

Prostym sposobem jest przekonwertowanie go na ciąg JSON, jak na poniższym przykładzie:

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

Następnie zapisz ciąg we wspólnych preferencjach. Gdy będziesz go potrzebować, po prostu pobierz ciąg ze wspólnych preferencji i przekonwertuj z powrotem na JSONArray lub JSONObject (zgodnie z wymaganiami).

Gaurav Darji
źródło
2

Do pisania:

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

Do czytania:

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;
}
Benav
źródło
Wydaje się, że to rozsądna sugestia. Wszystkie wspólne kolekcje implementują Serializable, a podstawowe ciągi, liczby i daty są serializowane. Jedynym minusem byłaby wydajność.
androidguy
1

To jest kod wspólnych preferencji, którego używam z powodzeniem, Skorzystaj z tego linku :

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


    }

   }

SZCZĘŚLIWEGO KODOWANIA!

dondondon
źródło
0

Możesz użyć putStringSet

Dzięki temu możesz zapisać zestaw HashSet w swoich preferencjach, tak jak to:

Zapisać

Set<String> values;

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

Editor editor = sharedPref.edit();

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

Odzyskaj

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

Editor editor = sharedPref.edit();

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

PutStringSet dopuszcza tylko zestaw i jest to lista nieuporządkowana .

Daniel Beltrami
źródło
0

Kiedy mnie to podsunęło, dostałem rozwiązanie do serializacji, w którym możesz serializować swój ciąg, ale ja też wymyśliłem hack.

Przeczytaj to tylko, jeśli nie czytałeś o serializacji, w przeciwnym razie zejdź na dół i przeczytaj mój hack

Aby uporządkować elementy tablicy, możemy serializować tablicę w jeden ciąg (tworząc nową klasę ObjectSerializer (skopiuj kod z - www.androiddevcourse.com/objectserializer.html, zamień wszystko oprócz nazwy pakietu))

Wprowadzanie danych w preferencjach wspólnych: wprowadź opis obrazu tutaj

reszta kodu w linii 38 - wprowadź opis obrazu tutaj

Umieść następny argument jako taki, aby jeśli dane nie zostały pobrane, zwróciły pustą tablicę (nie możemy wstawić pustego ciągu, ponieważ kontener / zmienna jest tablicą, a nie ciągiem)

Jadąc do mojego hacka: -

Połącz zawartość tablicy w jeden ciąg, umieszczając jakiś symbol między każdym elementem, a następnie podziel go za pomocą tego symbolu podczas pobierania. Dzięki wspólnym preferencjom dodawanie i pobieranie String jest łatwe. Jeśli martwisz się o podział, po prostu wyszukaj „dzielenie łańcucha w java”.

[Uwaga: Działa to dobrze, jeśli zawartość twojej tablicy jest prymitywnego rodzaju, jak string, int, float, itp. Będzie działać dla złożonych tablic, które mają własną strukturę, przypuśćmy, że książka telefoniczna, ale scalanie i dzielenie stanie się nieco skomplikowane. ]

PS: Jestem nowy w Androidzie, więc nie wiem, czy to dobry hack, więc daj mi znać, jeśli znajdziesz lepsze hacki.

Ritveak
źródło