Android: SharedPreferences getStringSet () возвращает onlu [] или [1] после запуска приложения [duplicate]

Новое в 2014 году:

Особенно, если вы также заинтересованы в манипулировании данными в целом (включая сортировку, фильтрацию, подмножество, подведение итогов и т. д.), вам обязательно нужно взглянуть на dplyr, который поставляется с множеством функций, которые предназначены для облегчения вашей работы с кадрами данных и некоторыми другими типами баз данных. Он даже предлагает довольно сложный SQL-интерфейс и даже функцию для преобразования (большинства) SQL-кода непосредственно в R.

. Четыре функции, связанные с соединением в пакете dplyr, (цитата):

  • inner_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x, где в y есть соответствующие значения, а все столбцы из x и y
  • left_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x и все столбцы от x и y
  • semi_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x, где в y есть соответствующие значения, сохраняя только столбцы из x.
  • anti_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x, где в y нет совпадающих значений, сохраняя только столбцы из x

Здесь все здесь

Выбор столбцов может выполняться с помощью select(df,"column"). Если для вас недостаточно SQL-ish, то есть функция sql(), в которую вы можете ввести код SQL как есть, и он будет выполнять указанную вами операцию так же, как вы писали в R все время (для получения дополнительной информации , обратитесь к dplyr / database vignette ). Например, если применить правильно, sql("SELECT * FROM hflights") выберет все столбцы из таблицы dplyr «hflights» («tbl»).

56
задан joojaa 29 May 2014 в 09:17
поделиться

4 ответа

Эта «проблема» документирована на SharedPreferences.getStringSet .

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

Это нормально, но проблема возникает, когда вы пытаетесь его сохранить: Android сравнивает модифицированный HashSet, который вы пытаетесь для сохранения с помощью SharedPreferences.Editor.putStringSet с текущим, сохраненным на SharedPreference, и оба являются одним и тем же объектом !!!

Возможное решение состоит в том, чтобы сделать копию Set<String>, возвращенную SharedPreferences:

Set<String> s = new HashSet<String>(sharedPrefs.getStringSet("key", new HashSet<String>()));

Это делает s другим объектом, а строки, добавленные в s, не будут добавлены в набор, сохраненный внутри SharedPreferences.

Другим обходным решением, которое будет работать, является использование одной и той же транзакции SharedPreferences.Editor для хранения другого более простого предпочтения (например, целочисленного или логического), единственное, что вам нужно, это заставить, чтобы хранимое значение отличалось для каждой транзакции (например, вы можете сохранить размер набора строк).

128
ответ дан Michał Tajchert 22 August 2018 в 04:57
поделиться
  • 1
    Я уже +1, но не могли бы вы предоставить ссылку на источник, подтверждающий ваше утверждение: «Android сравнивает измененный HashSet, который вы пытаетесь сохранить, используя SharedPreferences.Editor.putStringSet с текущим, хранящимся в SharedPreference & quot; – Mr_and_Mrs_D 24 December 2013 в 19:54
  • 2
    Я весь день бил головой о стену! Благодаря!!! – Tim 22 January 2016 в 03:03
  • 3
    Второй вариант (сохранить счетчик) работал отлично для меня. Благодаря! – MarionaDSR 24 March 2017 в 20:56
  • 4
    Отработал 9 часов, глядя на мой код на этом. Благодаря тонну. – AnupamChugh 27 July 2018 в 19:39

Это поведение задокументировано так:

from getStringSet:

"Обратите внимание, что вы не должны изменять экземпляр набора, возвращенный этим вызовом. сохраненных данных не гарантируется, если вы это сделаете, и ваша способность вообще не изменять этот экземпляр. "

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

12
ответ дан Dale 22 August 2018 в 04:57
поделиться
  • 1
    Сегодня вечером я отредактировал свой собственный ответ. Я понял, что это правильно документировано, но когда вы много раз пишете код, вы не смотрите на документацию в таких вещах. Это единственная причина, чтобы сохранить этот запрос + ответ, ИМХО, потому что это класс полезности, и такое объяснение может помочь кому угодно. Спасибо за разъяснение – JoseLSegura 26 December 2012 в 11:05

Ищет решение для одной и той же проблемы, разрешил его:

1) Извлеките существующий набор из общих настроек

2) Сделайте копию

3) Обновить копию

4) Сохранить копию

SharedPreferences.Editor editor = sharedPrefs.edit();
Set<String> oldSet = sharedPrefs.getStringSet("key", new HashSet<String>());

//make a copy, update it and save it
Set<String> newStrSet = new HashSet<String>();    
newStrSet.add(new_element);
newStrSet.addAll(oldSet);

editor.putStringSet("key",newStrSet); edit.commit();

Почему

3
ответ дан s-hunter 22 August 2018 в 04:57
поделиться

Я пробовал все вышеперечисленные ответы, никто не работал для меня. Поэтому перед добавлением нового элемента в список старого общего pref, я сделал следующие шаги

  1. , сделайте его копию
  2. вызовите метод с указанной копией в качестве параметра к этому методу.
  3. внутри этого метода очистить общий префикс, который удерживает эти значения.
  4. добавить значения, присутствующие в копии, в очищенное разделяемое предпочтение, оно будет рассматривать его как новое.
    public static void addCalcsToSharedPrefSet(Context ctx,Set<String> favoriteCalcList) {
    
    ctx.getSharedPreferences(FAV_PREFERENCES, 0).edit().clear().commit();
    
    SharedPreferences sharedpreferences = ctx.getSharedPreferences(FAV_PREFERENCES, Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedpreferences.edit();
    editor.putStringSet(FAV_CALC_NAME, favoriteCalcList);
    editor.apply(); }
    

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

0
ответ дан Swapnil 22 August 2018 в 04:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: