1

В настоящее время я использую SharedPreferences, чтобы отслеживать список элементов для выполнения работы в BroadcastReceiver, запускаемом через AlarmManager. Все работает отлично, за исключением конкретного сценария. Когда я запускаю новый элемент для выполнения работы, пусть он выполняет эту работу, а затем удаляет этот элемент (все с помощью редактирования SharedPreferences), он прекрасно работает во время работы приложения. Когда в списке нет ничего, и я открываю Диспетчер задач и убиваю приложение, внезапно появляется элемент в BroadcastReceiver (который все еще работает после закрытия приложения). Что вызывает такое поведение? Должен ли я просто убить всех получателей при выходе из приложения? Возвращает ли действие закрытие по умолчанию другого объекта SharedPreferences, когда приемник все еще работает?SharedPreferences - Activity and BroadcastReceiver

Код для добавления/удаления элементов из SharedPreferences объекта

final SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME, 
       Context.MODE_PRIVATE); 
final Editor editor = prefs.edit(); 
mUpdates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, new HashSet<String>()); 

if (!mUpdates.contains(key)) { 
    mUpdates.add(key); 
} else { 
    mUpdates.remove(key); 
} 
editor.putStringSet(Config.PREFS_KEY_ACTIVE_TASKS, mUpdates); 
editor.apply(); 

Радиопередача приемник код

public void onReceive(Context context, Intent intent) { 
    SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME, Context.MODE_PRIVATE); 
    if(prefs.contains(Config.PREFS_KEY_ACTIVE_TASKS)) { 
     Set<String> updates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, null); 
     if(updates != null) { 
      Log.d("RECEIVER","Size="+updates.size()); 
      for(String key : updates) { 
       EntityChangeManager.notifyListeners(key); 
      } 
     } 
    } 
} 

Когда я запускаю код для добавления/удаления объектов из исходного списка, как и ожидалось, I см

04-30 20:04:44.165: D/RECEIVER(27079): Size=1 
04-30 20:04:44.165: D/RECEIVER(27079): Size=0 

Когда я убиваю приложение я вижу

04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapUtilization:0.25 
04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapIdealFree:8388608 
04-30 20:04:43.254: D/ActivityThread(27079): setTargetHeapConcurrentStart:2097152 
04-30 20:04:43.264: D/RECEIVER(27079): Size=1 

Достопримечательности:

  • Приемник работает каждый второй
  • Приемник запускается из AlarmManager
  • Никаких специальных настроек в декларации
  • Это повторяется после деинсталляции приложения , очистка всех префов в приемнике (в случае, если он использовал другой)
+0

Похоже, что это напрямую связано с использованием StringSet, хотя я не определил причину. Отправлено вручную для сборки и анализа строки вместо использования stringset. – methodin

ответ

2

Изменение editor.apply(); - editor.commit(). Изменение может не записываться на диск, когда вы убиваете приложение. Из официального документа на http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply()

В отличии от фиксации(), который записывает свои предпочтения к постоянной памяти синхронно, применяются() совершает свои изменения в SharedPreferences в памяти сразу, а начинает асинхронные фиксации на диск, и вы выиграли» t быть уведомленным о любых отказах. Если другой редактор этой SharedPreferences выполняет регулярную фиксацию(), а apply() все еще неактивен, commit() будет блокироваться до тех пор, пока все асинхронные транзакции не будут завершены, а также сам commit.

+0

Спасибо за ответ. Я изначально использовал фиксацию и переключился на применение, чтобы попытаться решить проблему. Оба работали одинаково. Оказывается, функциональность StringSet не понимает изменений в ее содержимом, поэтому даже когда вы редактируете данные, это похоже на sharedpref. – methodin

1

Если вы работаете в каких-либо нюансов с помощью StringSet решения, чтобы написать еще один атрибут в SharedPreferences объект (например, StringSet.size()) в тандеме с самим StringSet. Причина в том, что библиотека SharedPreferences сравнивает объект с сохраненным объектом, а добавление/удаление данных не обязательно приводит к изменению самого объекта, поэтому он выглядит так, как будто нет различий.

Можно проверить размер объекта, и если вы его редактируете, то вместо редактирования его просто установите для объекта значение null, прежде чем сохранять его в SharedPreferences. Я выбрал вторую настройку sharedpref, и с тех пор она отлично справилась.

+0

Спасибо, это хорошо знать. –

1

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

Проблема: старые значения, которые извлекаются из BroadcastReceiver. Это вызвано SharedPreferences, который не обновляет содержимое StringSet, потому что это тот же объект.

следующие вещи были изменены, чтобы обеспечить постоянное хранение с помощью SharedPreferences (я не знаю, какие вещи способствовали решению):

  • В манифесте я был android:process=":remote", который должен был быть удален.
  • Я использовал Context.MODE_MULTI_PROCESS как режим в sharedpreferences (context.getSharedPreferences(ref,Context.MODE_MULTI_PROCESS))
  • И, наконец (из-за this пост), первым совершает значение null решить мою проблему:
editor.putStringSet(ref,null); 
    editor.commit(); 
    editor.putStringSet(ref, valuesToBeStored); 

я, если не знаю, необходимы первые два изменения.

+0

Это не дает ответа на вопрос. Когда у вас будет достаточно [репутации] (http://stackoverflow.com/help/whats-reputation), вы сможете [прокомментировать любое сообщение] (http://stackoverflow.com/help/privileges/comment); вместо этого [предоставить ответы, которые не требуют разъяснений у аськи) (http://meta.stackexchange.com/questions/214173/why-do-need-50-reputation-to-comment-what-can- я-делать-вместо этого). - [Из обзора] (/ review/low-quality-posts/12144285) –

+0

Этот ответ относится к проблеме при использовании StringSet. Этот ответ дает решение проблемы «Когда нет ничего в списке, и я открываю диспетчер задач и убиваю приложение, внезапно элемент появляется в BroadcastReceiver». Ожидаемое поведение программы должно состоять в том, что последним сохраненным значением должно быть полученное значение. – gillesC

+1

Я отредактировал свой ответ, поэтому проблема, связанная с вопросом, лучше ответить. – gillesC

Смежные вопросы