Android'de SharedPreferences'a bir dizi veya nesne eklemek mümkün mü


Yanıtlar:


60

Dolayısıyla, Veri Depolama'daki android geliştirici sitesinden :

Kullanıcı tercihleri

Paylaşılan tercihler , bir kullanıcının seçtiği zil sesi gibi "kullanıcı tercihlerini" kaydetmeye yönelik değildir . Uygulamanız için kullanıcı tercihleri ​​oluşturmakla ilgileniyorsanız, otomatik olarak kalıcı olacak (paylaşılan tercihleri ​​kullanarak) kullanıcı tercihleri ​​oluşturmanız için bir Etkinlik çerçevesi sağlayan PreferenceActivity'ye bakın.

Bu yüzden, sadece kalıcı olan anahtar-değer çiftleri olduğu için sorun olmadığını düşünüyorum.

Orijinal poster için bu o kadar da zor değil. Sadece dizi listenizi yineleyin ve öğeleri ekleyin. Bu örnekte basit olması için bir harita kullanıyorum ama bir dizi listesi kullanabilir ve uygun şekilde değiştirebilirsiniz:

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

Anahtar / değer çiftlerini tekrar okumak için benzer bir şey yaparsınız. Bunun işe yarayıp yaramadığını bana bildirin.

Güncelleme: API seviyesi 11 veya üzerini kullanıyorsanız, bir Dize Kümesi yazmak için bir yöntem vardır .


Teşekkürler Noel, bunu kodun yardımıyla çözdüm. Yine de kod yazım hatalarını izleyin. ;)
zsniperx

Bir cazibe gibi çalıştı ... Thx
Bala Vishnu

74

API seviyesinden bağımsız olarak, SharedPreferences'daki String dizilerini ve Nesne dizilerini kontrol edin


DİZİ KAYDET

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

YÜK DÜZENİ

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
Bu berbat bir teknik. Bu blogdaki yorumlara bakın : "Bu yaklaşımla ilgili sorun, tercihlerinizi kirletmenizdir. Diyelim ki, 100 girişli bir diziyi kaydedip ardından onu 2'ye küçültün. önce temizleyin. "
Kyle Ivey

2
Temizleniyor yerine kolay bir ektir
Sherif elKhatib

Teşekkürler, çok güzel stilli kod. Bu SO'daki en sevdiğim cevaplardan biri. :)
Martin Pfeffer

3
Bu yanlış bir yaklaşım !!! 100 değişken eklemeye çalışıyorsun ve bu korkunç !! bunun yerine bu yöntemi jsonarray ve jsonbj ile kullanabilirsiniz: stackoverflow.com/a/8287418/2652368
Amir Hossein Ghasemi

@AmirHosseinGhasemi her iki yaklaşım da aslında hacklerdir. teşekkürler
Sherif elKhatib

60

Yazmak,

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

Okumak,

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

Paylaşılan tercihler , API Seviye 11'de a getStringSetve putStringSetyöntemleri tanıttı , ancak bu, Android'in eski sürümleriyle (hala popüler olan) uyumlu değil ve aynı zamanda dize kümeleriyle sınırlı.

Android daha iyi yöntemler sağlamaz ve bunları kaydetmek ve yüklemek için haritalar ve diziler üzerinde döngü yapmak, özellikle diziler için çok kolay ve temiz değildir. Ancak daha iyi bir uygulama o kadar da zor değil:

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

Artık bu beş yöntemle herhangi bir koleksiyonu paylaşılan tercihlere kaydedebilirsiniz. Çalışma JSONObjectve JSONArrayçok kolaydır. Sen kullanabilirsiniz JSONArray (Collection copyFrom)bir hale getirmek için public kurucu JSONArrayherhangi bir Java toplama ve kullanım out JSONArray'ın getelemanları erişmek için yöntemler.

Paylaşılan tercihler için bir boyut sınırı yoktur (cihazın depolama sınırlarının yanı sıra), bu nedenle bu yöntemler, uygulamanızda bazı koleksiyonlar için hızlı ve kolay bir depolama istediğiniz çoğu olağan durumda çalışabilir. Ancak JSON ayrıştırması burada gerçekleşir ve Android'deki tercihler dahili olarak XML olarak depolanır, bu nedenle megabaytlarca veriyle uğraşırken diğer kalıcı veri deposu mekanizmalarını kullanmanızı öneririm.


7
JSON ile gidiyorsanız, belki gson: code.google.com/p/google-gson adresine bakabilirsiniz - java nesnelerini JSON'a ve JSON'dan dönüştürür.
FeatureCreep

Bu ilginç bir kombinasyon olurdu.
Mostafa

17

Gson google kitaplığı [1] kullanarak karmaşık nesne depolaması için kolay mod

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/


En iyisi! Bunu CEVAP olarak işaretle!
Renan Franca

3

Aşağıdaki kodla tercihler.xml dosyama bir dizi bel boyutu (zaten array.xml'de oluşturulmuş) yükledim. @ dizi / pant_inch_size, tüm dizinin kimliğidir.

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

Bu, menüyü dizideki seçeneklerle doldurdu. Varsayılan boyutu 34 olarak ayarladım, böylece menü açıldığında, 34 boyutunun önceden seçildiğini görüyorlar.


Merhaba Keith, cevabın için teşekkürler. Bir siparişi saklamam gerekiyor ve tercih kullanıcı arayüzüyle çalışmıyorum, bu yüzden kodunuzun başarmam gereken şeyle eşleşmesini istemiyorum. Yine de teşekkürler
zsniperx

Ah!! Sorunuzu yanlış yorumladım, bunun için üzgünüm. Diğer okuyucular için, XML kodum basitçe array.xml dosyamdaki öğeleri alır ve bu örnekte varsayılan tercih "34" olarak önceden seçilmiş olarak bunları tercihler menüsüne yükler. Daha sonra bu özel tercih için "pantSizePref" ("anahtar") olan tanımlayıcıyı bulmak için java kullanıyorum.
Keith

2

Basit yol, aşağıdaki örnekte olduğu gibi JSON String'e dönüştürmektir:

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

Ardından dizeyi paylaşılan tercihlerde saklayın. İhtiyaç duyduğunuzda, paylaşılan tercihlerden dize alın ve tekrar JSONArray veya JSONObject'e dönüştürün (gereksiniminize göre).


2

Yazmak için:

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

Okumak için:

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

Bu sağlam bir öneri gibi görünüyor. Ortak koleksiyonların tümü Serileştirilebilir'i uygular ve temel Diziniz, Numaranız ve Tarihiniz Serileştirilebilirdir. Tek dezavantajı performans olacaktır.
androidguy

1

Bu, başarıyla kullandığım paylaşılan tercihler kodudur, bu bağlantıya bakın :

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


    }

   }

MUTLU KODLAMA!


0

PutStringSet'i kullanabilirsiniz

Bu, aşağıdaki gibi tercihlerinize bir HashSet kaydetmenize izin verir:

Kayıt etmek

Set<String> values;

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

Editor editor = sharedPref.edit();

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

Retrive

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

Editor editor = sharedPref.edit();

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

PutStringSet sadece bir Set'e izin verir ve bu sırasız bir listedir.


0

Bu sorunla karşılaştığımda, dizinizi serileştirebileceğiniz bir serileştirme çözümünü aldım, Ama ben de bir hack ile geldim.

Bunu sadece serileştirme hakkında okumadıysanız okuyun, yoksa aşağı inin ve hack'imi okuyun

Dizi öğelerini sırayla depolamak için, diziyi tek bir dizeye serileştirebiliriz (yeni bir sınıf ObjectSerializer oluşturarak (kodu kopyalayın - www.androiddevcourse.com/objectserializer.html, paket adı dışındaki her şeyi değiştirin))

Paylaşılan tercihe veri girme: görüntü açıklamasını buraya girin

38. satırdaki kodun geri kalanı - görüntü açıklamasını buraya girin

Sonraki argümanı bu olarak koyun, böylece veri alınmazsa boş dizi döndürür (boş dizge koyamayız çünkü konteyner / değişken bir dizidir, dize değil)

Hack'ime geliyor: -

Dizinin içeriğini, her öğenin arasına bir sembol koyarak tek bir dizede birleştirin ve ardından geri alırken bu sembolü kullanarak bölün. Dize eklemek ve almak, paylaşılan tercihlerle kolaydır. Bölme konusunda endişeleniyorsanız, "java'da bir dizeyi bölme" konusuna bakın.

[Not: Dizinizin içeriği string, int, float vb. Gibi ilkel türdeyse bu iyi çalışır. Kendi yapısı olan karmaşık diziler için çalışacaktır, varsayalım bir telefon rehberi, ancak birleştirme ve bölme işlemi bir biraz karmaşık. ]

Not: Android'de yeniyim, bu yüzden iyi bir hack olup olmadığını bilmiyorum, bu yüzden daha iyi hackler bulup bulamayacağınızı bilmeme izin verin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.