Ist es möglich, SharedPreferences unter Android ein Array oder Objekt hinzuzufügen?

82

Ich habe eines ArrayListvon Objekten, die einen Namen und einen Symbolzeiger haben, und ich möchte es in speichern SharedPreferences. Wie kann ich?

HINWEIS: Ich möchte die Datenbank nicht verwenden

zsniperx
quelle

Antworten:

59

Also von der Android-Entwicklerseite auf Datenspeicher :

Nutzerpreferenzen

Gemeinsame Einstellungen dienen nicht ausschließlich zum Speichern von "Benutzereinstellungen", z. B. dem von einem Benutzer ausgewählten Klingelton. Wenn Sie Benutzereinstellungen für Ihre Anwendung erstellen möchten, lesen Sie PreferenceActivity. Dort finden Sie ein Aktivitätsframework, mit dem Sie Benutzereinstellungen erstellen können, die automatisch beibehalten werden (unter Verwendung gemeinsamer Einstellungen).

Ich denke, es ist in Ordnung, da einfach nur Schlüssel-Wert-Paare bestehen bleiben.

Für das Originalplakat ist das nicht so schwer. Sie durchlaufen einfach Ihre Array-Liste und fügen die Elemente hinzu. In diesem Beispiel verwende ich der Einfachheit halber eine Karte, aber Sie können eine Array-Liste verwenden und sie entsprechend ändern:

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

Sie würden etwas Ähnliches tun, um die Schlüssel-Wert-Paare erneut zu lesen. Lassen Sie mich wissen, ob dies funktioniert.

Update: Wenn Sie API Level 11 oder höher verwenden, gibt es eine Methode zum Schreiben eines String-Sets

Noel
quelle
Danke Noel, ich habe es mit Hilfe Ihres Codes herausgefunden. Beachten Sie jedoch die Code-Tippfehler. ;)
zsniperx
Arbeitete wie ein Zauber ... Thx
Bala Vishnu
74

Überprüfen Sie unabhängig von der API-Ebene String-Arrays und Objekt-Arrays in SharedPreferences


ARRAY SPEICHERN

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

LADEN SIE 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
quelle
9
Dies ist eine schreckliche Technik. Siehe die Kommentare in diesem Blog: "Das Problem bei diesem Ansatz besteht darin, dass Sie Ihre Einstellungen verschmutzen. Angenommen, Sie speichern ein Array mit 100 Einträgen und verkleinern es dann auf 2. Sie haben immer noch 100 Einträge in Ihren Einstellungen, es sei denn, Sie räum es zuerst auf. "
Kyle Ivey
2
Aufräumen ist eine ziemlich einfache Ergänzung
Sherif elKhatib
Danke, sehr schön gestylter Code. Dies ist eine meiner Lieblingsantworten hier auf SO. :)
Martin Pfeffer
3
Das ist ein falscher Ansatz !!! Sie versuchen, 100 Variablen hinzuzufügen, und das ist schrecklich! Stattdessen können Sie diese Methode mit jsonarray und jsonbj verwenden: stackoverflow.com/a/8287418/2652368
Amir Hossein Ghasemi
@AmirHosseinGhasemi beide Ansätze sind eigentlich Hacks. danke
Sherif elKhatib
60

Schreiben,

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

Lesen,

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
quelle
31

Gemeinsame Einstellungen haben a getStringSetund putStringSetMethoden in API Level 11 eingeführt, dies ist jedoch nicht kompatibel mit älteren Android-Versionen (die immer noch beliebt sind) und ist auch auf Sätze von Zeichenfolgen beschränkt.

Android bietet keine besseren Methoden, und das Durchlaufen von Karten und Arrays zum Speichern und Laden ist nicht sehr einfach und sauber, insbesondere für Arrays. Aber eine bessere Implementierung ist nicht so schwer:

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

Mit diesen fünf Methoden können Sie jetzt jede Sammlung in freigegebenen Einstellungen speichern. Arbeiten mit JSONObjectund JSONArrayist sehr einfach. Sie können mit JSONArray (Collection copyFrom)öffentlichem Konstruktor ein , um JSONArrayaus jeder Java - Sammlung und Verwendung JSONArray‚s getMethoden , um die Elemente zuzugreifen.

Es gibt keine Größenbeschränkung für freigegebene Einstellungen (außer den Speicherbeschränkungen des Geräts), sodass diese Methoden in den meisten Fällen funktionieren können, in denen Sie eine schnelle und einfache Speicherung für eine Sammlung in Ihrer App wünschen. Hier findet jedoch eine JSON-Analyse statt, und die Einstellungen in Android werden intern als XML-Dateien gespeichert. Daher empfehle ich die Verwendung anderer persistenter Datenspeichermechanismen, wenn Sie mit Megabyte an Daten arbeiten.

Mostafa
quelle
7
Wenn Sie mit JSON arbeiten, lesen Sie vielleicht gson: code.google.com/p/google-gson - es konvertiert Java-Objekte in und von JSON.
FeatureCreep
Das wäre eine interessante Kombination.
Mostafa
17

Einfacher Modus für die Speicherung komplexer Objekte mit der Gson Google Library [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
quelle
Der beste! Markiere dies als die ANTWORT!
Renan Franca
3

Ich habe eine Reihe von Taillengrößen (die bereits in meiner Datei array.xml erstellt wurden) mit dem folgenden Code in meine Datei settings.xml geladen. @ array / pant_inch_size ist die ID des gesamten Arrays.

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

Dadurch wurde das Menü mit Auswahlmöglichkeiten aus dem Array gefüllt. Ich habe die Standardgröße auf 34 festgelegt. Wenn das Menü angezeigt wird, wird Größe 34 vorausgewählt.

Keith
quelle
Hallo Keith, danke für deine Antwort. Ich muss eine Bestellung speichern und arbeite nicht mit der bevorzugten Benutzeroberfläche, damit Ihr Code nicht mit dem übereinstimmt, was ich erreichen muss. Trotzdem danke
zsniperx
Ah!! Ich habe Ihre Frage falsch interpretiert, tut mir leid. Für alle anderen Leser erfasst mein XML-Code einfach Elemente aus meiner Datei array.xml und lädt sie in das Einstellungsmenü, wobei die Standardeinstellung in diesem Fall als "34" vorgewählt ist. Ich benutze dann Java, um den Bezeichner für diese bestimmte Präferenz zu finden, nämlich "pantSizePref" (der "Schlüssel").
Keith
2

Die einfache Möglichkeit besteht darin, sie wie im folgenden Beispiel in einen JSON-String zu konvertieren:

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

Speichern Sie dann die Zeichenfolge in den freigegebenen Einstellungen. Sobald Sie es benötigen, rufen Sie einfach eine Zeichenfolge aus den freigegebenen Einstellungen ab und konvertieren Sie sie zurück in JSONArray oder JSONObject (gemäß Ihren Anforderungen).

Gaurav Darji
quelle
2

Zum Schreiben:

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

Zum Lesen:

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
quelle
Dies scheint ein vernünftiger Vorschlag zu sein. Die allgemeinen Sammlungen implementieren alle Serializable, und Ihre grundlegende Zeichenfolge, Nummer und Datum sind serialisierbar. Der einzige Nachteil wäre die Leistung.
AndroidGy
1

Dies ist der Code für gemeinsame Einstellungen, den ich erfolgreich verwende. Siehe diesen 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());


    }

   }

GLÜCKLICHE CODIERUNG!

Dondondon
quelle
0

Sie können putStringSet verwenden

Auf diese Weise können Sie ein HashSet wie folgt in Ihren Einstellungen speichern:

sparen

Set<String> values;

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

Editor editor = sharedPref.edit();

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

Wiederholen

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

Editor editor = sharedPref.edit();

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

Das putStringSet erlaubt nur ein Set und dies ist eine ungeordnete Liste.

Daniel Beltrami
quelle
0

Als ich damit abgehört wurde, bekam ich die Serialisierungslösung, mit der Sie Ihre Zeichenfolge serialisieren können. Aber ich habe mir auch einen Hack ausgedacht.

Lesen Sie dies nur, wenn Sie nichts über Serialisierung gelesen haben. Andernfalls lesen Sie meinen Hack

Um Array-Elemente in der richtigen Reihenfolge zu speichern, können wir das Array in eine einzelne Zeichenfolge serialisieren (indem wir eine neue Klasse ObjectSerializer erstellen (kopieren Sie den Code von - www.androiddevcourse.com/objectserializer.html, ersetzen Sie alles außer dem Paketnamen).

Eingabe von Daten in gemeinsame Einstellungen: Geben Sie hier die Bildbeschreibung ein

der Rest des Codes in Zeile 38 - Geben Sie hier die Bildbeschreibung ein

Setzen Sie das nächste Argument wie folgt ein, damit, wenn Daten nicht abgerufen werden, ein leeres Array zurückgegeben wird (wir können keine leere Zeichenfolge setzen, da der Container / die Variable ein Array ist, das keine Zeichenfolge ist).

Kommen zu meinem Hack: -

Führen Sie den Inhalt des Arrays zu einer einzelnen Zeichenfolge zusammen, indem Sie zwischen den einzelnen Elementen ein Symbol einfügen, und teilen Sie es dann beim Abrufen mit diesem Symbol auf. Das Hinzufügen und Abrufen von Zeichenfolgen ist mit gemeinsamen Einstellungen einfach. Wenn Sie sich Sorgen um das Teilen machen, schauen Sie einfach nach "Teilen eines Strings in Java".

[Hinweis: Dies funktioniert einwandfrei, wenn der Inhalt Ihres Arrays primitiver Art ist, z. B. Zeichenfolge, Int, Float usw. Es funktioniert für komplexe Arrays, die eine eigene Struktur haben, beispielsweise ein Telefonbuch, aber das Zusammenführen und Aufteilen wird zu einem etwas komplex. ]]

PS: Ich bin neu in Android, also weiß ich nicht, ob es ein guter Hack ist, also lass mich wissen, ob du bessere Hacks findest.

Ritveak
quelle