Подтвердить что ты не робот

Android SharedPreferences String Set - некоторые элементы удаляются после перезагрузки приложения

Я сохраняю набор строк в общих настройках, если я его прочитаю. Я начинаю другие действия, возвращаюсь и читаю снова, все в порядке. Если я закрою приложение и запустил его снова, я получаю набор, но только с одним элементом вместо 4. Это происходит все время. Есть ли известная проблема? Что я могу сделать неправильно?

В классе, что создается в методе oncreate приложения, у меня есть SharedPreferences и переменная SharePreferences.Editor. Я использую их в методах сохранения и загрузки.

public void saveFeedback(FeedbackItem feedbackItem) {
    checkSp();
    Set<String> feedbackSet = getFeedbacksSet();
    if(feedbackSet == null){
        feedbackSet = new HashSet<String>();
    }
    JSONObject json = createJSONObjectfromFeedback(feedbackItem);
    feedbackSet.add(json.toString());
    ed.putStringSet(CoreSetup.KEY_FEEDBACK, feedbackSet);
    ed.commit();
}

public Set<String> getFeedbacksSet(){
    checkSp();
    Set<String> ret = sp.getStringSet(CoreSetup.KEY_FEEDBACK, null);
    return ret;
}

private void checkSp(){
    if(this.sp == null)
        this.sp = applicationContext.getSharedPreferences(applicationContext.getPackageName(), Context.MODE_PRIVATE);
    if(this.ed == null)
        this.ed = this.sp.edit();
}

Я просто не понимаю, как это могло случиться, чтобы хранить все элементы во время работы приложения, а затем после перезагрузки не все элементы находятся в наборе. И я думаю, что если все элементы будут удалены, это может быть более приемлемым, чем некоторые предметы, и один элемент все еще существует. Есть ли объяснение?

4b9b3361

Ответ 1

Исходя из вашего вопроса, вы должны вызывать фиксацию только после того, как в набор добавлено 4 элемента. В вашем коде вы вызываете фиксацию для каждой обратной связи, которая перезапишет предыдущую обратную связь.

Обновление: http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet(java.lang.String, java.util.Set)

Note that you must not modify the set instance returned by this call. The consistency of the stored data is not guaranteed if you do, nor is your ability to modify the instance at all.

Это именно то, что вы делаете

Ответ 2

Эта "проблема" описана в SharedPreferences.getStringSet().

getStringSet() возвращает ссылку на сохраненный объект HashSet внутри SharedPreferences. Когда вы добавляете элементы к этому объекту, они фактически добавляются в SharedPreferences.

Обходной путь - сделать копию возвращенного набора и поместить новый набор в SharedPreferences. Я проверил это, и это работает.

В Котлине это было бы

    val setFromSharedPreferences = sharedPreferences.getStringSet("key", mutableSetOf())
    val copyOfSet = setFromSharedPreferences.toMutableSet()
    copyOfSet.add(addedString)

    val editor = sharedPreferences.edit()
    editor.putStringSet("key", copyOfSet)
    editor.apply() // or commit() if really needed

Ответ 3

Попробуйте создать копию своего набора, и вы можете сохранить его в тех же привилегиях:

private Set<String> _setFromPrefs;


public void GetSetFromPrefs()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
    Set<String> someSets = sharedPref.getStringSet("some_sets", new HashSet<String>() );
    _setFromPrefs = new HashSet<>(someSets); // THIS LINE CREATE A COPY
}


public void SaveSetsInPrefs()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putStringSet("some_sets", _setFromPrefs);
    editor.commit();
}

Ответ 4

В соответствии с документом набор строк в SharedPreferences должен рассматриваться как неизменный, все идет на юг, пытаясь его модифицировать. Работа вокруг была бы: Получите существующий набор, сделайте его копию, обновите копию, а затем сохраните ее в общих настройках, например, это новый набор.

Set<String> feedbackSet = getFeedbacksSet();
if(feedbackSet == null){
    feedbackSet = new HashSet<String>();
}

//make a copy of the set, update the copy and save the copy
Set<String> newFeedbackSet = new HashSet<String>();
JSONObject json = createJSONObjectfromFeedback(feedbackItem);
newFeedbackSet.add(json.toString());
newFeedbackSet.addAll(feedbackSet);
ed.putStringSet(CoreSetup.KEY_FEEDBACK, newFeedbackSet);
ed.commit();

Ответ 5

В этой же проблеме. Решил его, очистив редактор после создания экземпляра и до его совершения.

sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    sFavList = sPrefs.getStringSet(context.getResources().getString(R.string.pref_fav_key), null);
    sEditor = sPrefs.edit();
    sEditor.clear(); // added clear, now Set data persists as expected
    if (sFavList == null) sFavList = new HashSet<>();
    sFavList.add(title);
    sEditor.putStringSet(context.getResources().getString(R.string.pref_fav_key), sFavList).apply();

Я попытался создать копию, как предложили другие, но это не сработало для меня.

Нашел это решение здесь.

Ответ 6

Сохранить строку в общих настройках

   SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
   editor.putString("text", mSaved.getText().toString());
   editor.commit();

Чтобы извлечь данные из общих настроек

 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 String restoredText = prefs.getString("text", null);