web-dev-qa-db-ja.com

SharedPreferencesを使用して複数の値を保存するにはどうすればよいですか?

辞書アプリを開発しています。私のアプリでは、ユーザーがお気に入りの単語を保存したいと思っていると思います。 SharedPreferencesを使用してこれらの値を保存することにしました(SQLiteとファイルの方が優れていることは承知していますが、「SharedPreferences」に固執しているので、そのまま続けてください)。

以下は私のコードです:

@Override
public void onClick(View v) {                                       
    SharedPreferences faves = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    { 
        SharedPreferences.Editor editor = faves.edit();
        editor.putString("favourite", mSelectedDB + "::" + mCurrentWordId + "::" + mCurrentWord + ",");
        editor.commit();    
    }
    Log.i(CONTENT_TAG,"Favourite saved!");

    Toast toast = Toast.makeText(ContentView.this, R.string.messageWordAddedToFarvourite, Toast.LENGTH_SHORT);
    toast.show();   
}

問題は、お気に入りの単語が複数保持されないことです。つまり、お気に入りの単語が1つだけ保存され、新しい単語が追加されると、前の単語は消去されます。

では、この問題を解決するために、上記のコードをどのように編集できますか?

助けてもらえますか?どうもありがとうございました。

11
Niamh Doyle

複数のお気に入りを保存できます 1つの文字列に多数のお気に入りを追加し、各お気に入りアイテムをカンマで区切って、1つの設定で保存できます。次に、convertStringToArrayメソッドを使用して文字列配列に変換できます。これが完全なソースコードです。
MyUtilityメソッドを使用して、複数のお気に入りのアイテムを保存します。

            MyUtility.addFavoriteItem(this, "Sports");
            MyUtility.addFavoriteItem(this, "Entertainment");

保存されたすべてのお気に入りの文字列配列を取得します

String[] favorites = MyUtility.getFavoriteList(this);// returns {"Sports","Entertainment"};

これらのメソッドを別のUtilityクラスに保存します

 public abstract class MyUtility {

    public static boolean addFavoriteItem(Activity activity,String favoriteItem){
        //Get previous favorite items
        String favoriteList = getStringFromPreferences(activity,null,"favorites");
        // Append new Favorite item
        if(favoriteList!=null){
            favoriteList = favoriteList+","+favoriteItem;
        }else{
            favoriteList = favoriteItem;
        }
        // Save in Shared Preferences
        return putStringInPreferences(activity,favoriteList,"favorites");
    }
    public static String[] getFavoriteList(Activity activity){
        String favoriteList = getStringFromPreferences(activity,null,"favorites");
        return convertStringToArray(favoriteList);
    }
    private static boolean putStringInPreferences(Activity activity,String nick,String key){
        SharedPreferences sharedPreferences = activity.getPreferences(Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(key, nick);
        editor.commit();                        
        return true;        
    }
    private static String getStringFromPreferences(Activity activity,String defaultValue,String key){
        SharedPreferences sharedPreferences = activity.getPreferences(Activity.MODE_PRIVATE);
        String temp = sharedPreferences.getString(key, defaultValue);
        return temp;        
    }

    private static String[] convertStringToArray(String str){
        String[] arr = str.split(",");
        return arr;
    }
}

必要な場合お気に入りを追加。次に、SharedPreferenceからお気に入りの文字列を取得し、カンマとお気に入りのアイテムを追加して、SharedPreferenceに保存し直します。
*区切り文字には、カンマの代わりに他の文字列を使用できます。

19

SharedPreferencesは単純なキー/値を介して機能するため、同じキーに新しい値を指定すると、前の値が上書きされます。あなたがやろうとしていることをする唯一の方法は、異なるキーを使うことです。これは、あなたがやろうとしていることにSharedPreferencesを使うべきではないという事実への一種のヒントです。

7
LuxuryMode

HoneycombはputStringSetメソッドを追加したので、Honeycomb以外のものをサポートする必要がない場合はそれを使用できます。

@Override
public void onClick(View v) {
    SharedPreferences faves = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    {
        Set<String> faveSet = faves.getStringSet("favourite");
        faveSet.add(mSelectedDB + "::" + mCurrentWordId + "::" + mCurrentWord + ",");
        SharedPreferences.Editor editor = faves.edit();
        editor.putStringSet("favourite", faveSet);
        editor.commit();
    }
    Log.i(CONTENT_TAG,"Favourite saved!");

    Toast toast = Toast.makeText(ContentView.this, R.string.messageWordAddedToFarvourite, Toast.LENGTH_SHORT);
    toast.show();
}

Honeycomb以前のデバイスのサポートが必要な場合は、独自のスキームを考え出す必要があります。

1つの可能性は、単語を1つの設定でコンマ区切り値として格納することです。

もう1つは、新しい単語「favourite1」、「favourite2」、「favourite3」ごとに新しいキーを生成し、単語数を格納するために使用する別の設定を行うことです。

5
Brigham

ボタンをクリックするたびに、既存のキーfavoriteを使用してお気に入りの単語を保存し、それを上書きします。複数の単語を保存するには、異なるキーで単語を保存する必要があります。したがって、お気に入りの単語を保存するたびに、次のことができます。

private static int incrementedValue = 0;
...
@Override
public void onClick(View v) {
    SharedPreferences faves = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

    SharedPreferences.Editor editor = faves.edit();
    editor.putString("favourite" + incrementedValue, mSelectedDB + "::" + mCurrentWordId + "::" + mCurrentWord + ",");
    editor.commit();

    Log.i(CONTENT_TAG,"Favourite saved!");

    Toast toast = Toast.makeText(ContentView.this, R.string.messageWordAddedToFarvourite, Toast.LENGTH_SHORT);
    toast.show();
    incrementedValue++;
}
2
Luksprog

これは、実際の設定ストレージが文字列のリストではなく、単一のリストであるためです。したがって、putString()と言うと、前の値が上書きされます。複数のオブジェクトを単一の設定文字列に格納する良い方法は、JSONを使用することです。値をシリアル化してから書き込むだけです。また、必要な複雑さのオブジェクトに直接変換できるという利点もあります。このルートを使用する場合は、 Jackson の使用を検討してください。

1
dmon

TreeMap(またはSerializableを実装する他のタイプのリスト)を使用できます。最近、お気に入りのリストを処理した方法は次のとおりです。 TreeMapでは、Favoriteは私が使用するクラスです。あなたの場合、代わりにTreeMap <Integer、String>を使用することができます。

private static TreeMap<Integer, Favourite> favourites;

...
...
...

// load favourites
FileInputStream fis=null;
ObjectInputStream ois = null;
try {
    fis = context.openFileInput(context.getString(R.string.favourites_file));
    try {
    ois = new ObjectInputStream(fis);
    favourites = (TreeMap<Integer, Favourite>) ois.readObject();
    } catch (StreamCorruptedException e) {
    } catch (IOException e) {
    } catch (ClassNotFoundException e) {
    }
} catch (FileNotFoundException e) {
} finally {
    try {
    if (ois!=null){
        ois.close();
    }
    } catch (IOException e) {
    }    
}

if (favourites==null){
    favourites = new TreeMap<Integer, Favourite>();     
}

...
...
...

// save favourites
FileOutputStream fos=null;
ObjectOutputStream oos=null;
try {
    fos = context.openFileOutput(context.getString(R.string.favourites_file), MODE_PRIVATE);
    try {
    oos = new ObjectOutputStream(fos);
    oos.writeObject(favourites);
    } catch (IOException e) {
    }
} catch (FileNotFoundException e) {
} finally {
    if (oos!=null){
    try {
        oos.close();
    } catch (Exception e2) {

    }
    }    
}

値を区切るために行っている「::」を回避することもできます。

お役に立てば幸いです...

1
Simon