AndroidのSharedPreferencesに配列またはオブジェクトを追加することは可能ですか?


83

私が持っているArrayList名前とアイコンポインタを持っていると私はそれを保存したいオブジェクトのをSharedPreferences。どのようにできるのか?

注:データベースを使用したくない

回答:


60

したがって、データストレージのAndroid開発者サイトから:

ユーザー設定

共有設定、ユーザーが選択した着信音などの「ユーザー設定」を保存するためだけのものではありません。アプリケーションのユーザー設定の作成に関心がある場合は、PreferenceActivityを参照してください。これは、(共有設定を使用して)自動的に永続化されるユーザー設定を作成するためのアクティビティフレームワークを提供します。

したがって、永続化されるのは単にキーと値のペアであるため、問題ないと思います。

元のポスターにとって、これはそれほど難しいことではありません。配列リストを繰り返し処理してアイテムを追加するだけです。この例では、簡単にするためにマップを使用していますが、配列リストを使用して適切に変更できます。

// 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 2010年

チャームのように働いた... Thx
Bala Vishnu

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エントリがあります。最初にそれをきれいにしてください。」
カイルアイビー2013年

2
クリーンアップはかなり簡単な追加です
Sherif elKhatib 2013年

おかげで、とても素敵なスタイルのコード。これは、SOでの私のお気に入りの回答の1つです。:)
Martin Pfeffer 2014年

3
これは間違ったアプローチです!!! 100個の変数を追加しようとすると、これはひどいです!! 代わりに、jsonarrayとjsonbjでこのメソッドを使用できます:stackoverflow.com/a/8287418/2652368
Amir Hossein

@AmirHosseinGhasemiどちらのアプローチも実際にはハックです。ありがとう
Sherif elKhatib 2015

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

共有設定では、APIレベル11でメソッドgetStringSetputStringSetメソッドが導入されましたが、これは古いバージョンの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();
        }
    }
}

これで、この5つの方法を使用して、任意のコレクションを共有設定に保存できます。作業JSONObjectJSONArray非常に簡単です。JSONArray (Collection copyFrom)パブリックコンストラクターを使用してJSONArrayJavaコレクションを作成し、JSONArraygetメソッドを使用して要素にアクセスできます。

共有設定にはサイズ制限がないため(デバイスのストレージ制限を除く)、これらの方法は、アプリ内のコレクション用にすばやく簡単にストレージが必要な通常のほとんどの場合に機能します。ただし、JSON解析はここで行われ、Androidの設定は内部でXMLとして保存されるため、メガバイトのデータを処理する場合は、他の永続的なデータストアメカニズムを使用することをお勧めします。


7
JSONを使用する場合は、gson:code.google.com/p/google-gsonを確認してください。JavaオブジェクトをJSONとの間で変換します。
featureCreep 2012

それは興味深い組み合わせになるでしょう。
モスタファ2012

17

Gsongoogleライブラリを使用した複雑なオブジェクトストレージのイージーモード[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/


最高のもの!これを回答としてマークしてください!
レナンフランカ

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が事前に選択されていることがわかります。


こんにちはキース、あなたの応答に感謝します。注文を保存する必要がありますが、設定UIを使用しないため、コードが達成する必要のあるものと一致しません。とにかくありがとう
zsniperx 2010年

ああ!私はあなたの質問を誤解しました、それについて申し訳ありません。他のリーダーの場合、私のXMLコードは、array.xmlファイルからアイテムを取得し、それらを設定メニューにロードします。この場合、デフォルトの設定は「34」として事前に選択されています。次に、Javaを使用して、この特定の設定の識別子である「pantSizePref」(「キー」)を見つけます。
キース

2

簡単な方法は、以下の例のようにJSON文字列に変換することです。

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を実装しており、基本的な文字列、数値、日付はSerializableです。唯一の欠点はパフォーマンスです。
androidguy 2016年

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はセットのみを許可し、これは順序付けられていないリストです。


0

これに悩まされたとき、文字列をシリアル化できるシリアル化ソリューションを手に入れましたが、ハックも思いつきました。

シリアル化について読んでいない場合にのみこれを読んでください。そうでない場合は、ダウンして私のハックを読んでください。

配列アイテムを順番に格納するために、配列を単一の文字列にシリアル化できます(新しいクラスObjectSerializerを作成します(コードを– www.androiddevcourse.com/objectserializer.htmlからコピーし、パッケージ名以外のすべてを置き換えます))

共有設定にデータを入力する: ここに画像の説明を入力してください

38行目の残りのコード- ここに画像の説明を入力してください

次の引数をこのように配置して、データが取得されない場合に空の配列を返すようにします(空の文字列を配置することはできません。コンテナ/変数は文字列ではなく配列です)

私のハックに来る:-

各アイテムの間に記号を入れて配列の内容を1つの文字列にマージし、その記号を使用して配列を取得します。文字列の追加と取得は、設定を共有することで簡単に行えます。分割が心配な場合は、「Javaで文字列を分割する」を調べてください。

[注:これは、配列の内容がstring、int、floatなどのプリミティブな種類の場合は正常に機能します。電話帳を想定すると、独自の構造を持つ複雑な配列でも機能しますが、マージと分割は少し複雑です。]

PS:私はAndroidを初めて使用するので、それが良いハックかどうかわからないので、もっと良いハックを見つけたかどうかはわかりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.