Когда Android SharedPreferences commit() возвращает false?
В моем приложении я храню важные данные в SharedPreferences
- он работает, как мне нужно. Теперь я хочу создавать сообщения журнала для некоторых неправильных ситуаций.
У меня есть сообщение о ситуации, когда настройки пусты или просто бросает какое-то исключение во время загрузки. Только некорректная ситуация при сохранении может появиться, если метод commit()
возвращает false - я не знаю, почему это может произойти, и что я должен делать в этом случае.
Итак, вопрос в том, когда метод commit()
возвращает false? И может ли while(!editor.commit()) {;}
быть решением для успеха?
Ответы
Ответ 1
Во-первых, вы никогда не захотите делать:
while(!editor.commit()) {;}
. Если вы хотите повторить фиксацию, вы сделали бы это несколько раз, а не цикл навсегда.
Относительно того, когда commit() возвращает -1:
Оба commit() и apply() вносят изменения в память, а затем заставляют вызовы записывать изменения на диск (для каждого источника). commit() ожидает возврата записи диска для возврата результатов. Таким образом, ответ на ваш вопрос: "При сохранении состояния предпочтения на диске происходит сбой для вашего конкретного вызова commit()". Поскольку изменения были отражены в памяти, они могут быть записаны или не записаны на диск другим вызовом commit() или apply() до или после вашей попытки записи на диск (думать о гоночных потоках). Поскольку нет кода для отката обновления памяти, а SharedPreferences - одиночные (для каждого источника), другие компоненты в вашем приложении будут видеть ваши изменения, даже если они не сохраняются до диск.
Таким образом, цикл несколько раз (а не навсегда), чтобы обеспечить фиксацию() записи на диск, кажется прекрасным, чтобы вы могли пройти мимо проблемы с прерывистым вводом-выводом, но это была бы редкая ситуация на основе ввода-вывода, выходит из строя. Если вам нужна совершенная область фиксации, вы хотели бы перечитать диск для проверки каждого вызова commit(), который имеет последствия для производительности, и является излишним для всех, кроме небольшого набора ситуаций.
Ответ 2
И может while (! editor.commit()) {;} быть решением для успеха в любом случае?
Операция выполняется синхронно и выполняется в потоке пользовательского интерфейса, поэтому, если у вас есть некорректная ошибка, которая возникает каждый раз, когда вы пытаетесь выполнить commit
, вы блокируете весь поток пользовательского интерфейса с помощью этого кода, и пользователь будет см. ANR. Нехорошо.
"apply", с другой стороны, является асинхронным, поэтому он не может блокировать поток пользовательского интерфейса, даже если вы будете выполнять его бесконечно долго.
В документации очень мало говорится о возможных неудачах операции фиксации (смотрите здесь здесь, здесь
и там). Настройки хранятся в файле xml, хранящемся на вашем внутреннем хранилище, поэтому одним из возможных сбоев может быть поврежденный XML файл. Второй можно найти в документации:
Обратите внимание, что когда два редактора изменяют предпочтения в одном и том же время, последнее для того, чтобы называть фиксацию.
Мало того, что вы можете сделать с поврежденным файлом, и не пытайтесь одновременно изменять настройки из разных мест.:)
Ответ 3
commit()
может возвращать false, если есть проблема с сохранением ваших данных.
Посмотрите на разницу между commit()
и apply()
, чтобы получить более ясное представление (взято из этого сайта)
применить()
Это немедленно сохраняет данные в памяти и сохраняет данные в диск на отдельном потоке. Таким образом, нет возможности блокировать основной нить (ваше приложение не будет зависать).
Это предпочтительный метод, но он доступен только с тех пор Пряники (API 9, Android 2.3).
фиксации()
Вызов этого будет сохранять данные в файл, однако процесс выполнялся в потоке, который называл это, останавливая все остальное пока сохранение не будет завершено. Он возвращает true при успешном завершении, false при сбое.
Используйте commit(), если вам требуется подтверждение успеха сохранения вашего данных или если вы разрабатываете устройства с предварительным указателем. совершить(), поскольку API 1
Ответ 4
Я бы приблизился к этой проблеме под другим углом.
Есть несколько альтернативных способов борьбы с этим.
Что я делаю, когда моя программа сначала запускается, я
инициализируйте значение моего общего предпочтения тестовому значению для проверки,
был изменен.
например:
editor.putInt("key", -1);
Затем в активности, где я извлекаю значение предпочтения:
int mySavedInt = this.pref.getInt("key", howIgetMyInt)
if(mySavedInt==-1){
// I know it not my saved int :) and hasn't been set.
}
Или для фактического использования общего предпочтения, чтобы определить, являются ли общие настройки
вы пытаетесь проверить, были ли обновлены.
например.
String getStatus = pref.getString("checkMySharedPreferences", "nil");
if (getStatus.equals("true")) {
// DO something.
} else {
Toast.makeText(this, "Set your preferences",
Toast.LENGTH_SHORT).show();
}
Затем, когда вы устанавливаете общие настройки, вы можете установить это значение в значение "true":
editor.putString("checkMySharedPreferences", "true");
editor.commit();
Еще одно предложение - убедиться, что вы проверяете данные перед обновлением общих настроек.
Таким образом, общие настройки не будут установлены, если данные недействительны.
if(my data is valid){
my shared preferences
commit
}
Последнее предложение - выполнить циклическую проверку (поскольку вы не уверены в этом процессе), и когда вы получаете свои данные для общих настроек и фиксируете их. Убедитесь, что пользовательский ввод равен новым общим настройкам. Хотя я не вижу в этом необходимости.
И для регистрации этих событий просто добавьте строки журнала, где это применимо.
Кроме того, просто сторонняя заметка, я не думаю, что это хорошая практика, чтобы исключить, если они не установлены, я считаю, что управление потоком программы может быть лучше обработано условными операторами, где очевидно, что будет runtime
ошибка. Сохраните обработку ошибок при проверке ввода пользователя.