Ответ 1
Наконец, я решил эту проблему. Один из других разработчиков добавил метод. Этот файл удаляет все файлы в папке data/data/packageName, кроме папки libs. Я думаю, они попытались удалить папку кэша.
Удален этот метод, и он решил.
SharedPreferences не работает корректно в одном из существующих приложений. Я пробовал много разных способов, но все еще не работал. Всегда начинайте загрузку значений по умолчанию.
Знаете ли вы, почему?
String default_user = "Default_User";
SharedPreferences pref = this.getSharedPreferences("TEST_SHAREDPREF", MODE_PRIVATE);
String user = pref.getString("user", default_user);
Log.d("SHARED CHECK", user);
if (user.equals(default_user)) {
SharedPreferences.Editor edit = pref.edit();
edit.putString("user", "new_user");
boolean ok = edit.commit();
user = pref.getString("user", default_user);
Log.d("SHARED WRITE", user);
Toast.makeText(this, user + " Save process: " + ok, Toast.LENGTH_LONG).show();
} else {
Log.d("SHARED READ", user);
Toast.makeText(this, "READ SharedPrefs: " + user, Toast.LENGTH_LONG).show();
}
EDIT: результаты журнала
чтобы этот блок всегда возвращал это значение, для которого используется неправильное приложение, и я не знаю, почему
//first run
SHARED CHECK Default_User
SHARED WRITE new_user
//each time after first
SHARED CHECK Default_User
SHARED WRITE new_user
Этот блок всегда возвращает это, для которого все приложения
//first run
SHARED CHECK Default_User
SHARED WRITE new_user
//each time after first
SHARED CHECK new_user
SHARED READ new_user
Наконец, я решил эту проблему. Один из других разработчиков добавил метод. Этот файл удаляет все файлы в папке data/data/packageName, кроме папки libs. Я думаю, они попытались удалить папку кэша.
Удален этот метод, и он решил.
При вызове apply()
или commit()
изменения сначала сохраняются в кэш памяти приложения, а затем Android пытается записать эти изменения на диск. Здесь происходит то, что ваш вызов commit()
терпит неудачу на диске, но изменения все еще сохраняются в кэше памяти приложения, как это видно в source.
Недостаточно прочитать значение из SharedPreferences, поскольку это значение может не отражать истинное значение, которое находится на диске, но только то, что хранится в кеше памяти.
То, что вы не можете сделать, это проверить логическое значение, возвращаемое вызовом commit()
, вероятно, это неверно для вашего проблемного случая. Вы можете повторить вызов commit()
пару раз, если возвращается false.
Просто используйте метод ниже и проверьте.
Создайте один Java
класс AppTypeDetails.java
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
public class AppTypeDetails {
private SharedPreferences sh;
private AppTypeDetails() {
}
private AppTypeDetails(Context mContext) {
sh = PreferenceManager.getDefaultSharedPreferences(mContext);
}
private static AppTypeDetails instance = null;
public synchronized static AppTypeDetails getInstance(Context mContext) {
if (instance == null) {
instance = new AppTypeDetails(mContext);
}
return instance;
}
// get user status
public String getUser() {
return sh.getString("user", "");
}
public void setUser(String user) {
sh.edit().putString("user", user).commit();
}
// Clear All Data
public void clear() {
sh.edit().clear().commit();
}
}
Теперь Установить значение SharedPreferences
.
AppTypeDetails.getInstance(MainActivity.this).setUser(<user name>);
Получить Форма значения SharedPreferences
.
String userName = AppTypeDetails.getInstance(MainActivity.this).getUser();
Теперь сделайте что-нибудь с именем пользователя.
Всегда проверяйте
if(userName.trim().isEmpty())
{
// Do anything here.
}
потому что In SharedPreferences
мы устанавливаем имя пользователя пустым ("")
или
вы можете установить имя пользователя null в SharedPreferences
, тогда вам нужно проверить
if(userName != null){
//do anything here
}
Для очистки данных из SharedPreferences
.
AppTypeDetails.getInstance(MainActivity.this).setUser("");
или
AppTypeDetails.getInstance(MainActivity.this).clear();
Одна вещь, которую вы могли бы попробовать, - получить новый экземпляр SharedPreference
после совершения и посмотреть, что произойдет:
SharedPreferences pref = this.getSharedPreferences("test", MODE_PRIVATE);
String user = pref.getString("user", default_user);
if (user.equals(default_user)) {
pref.edit().putString("user", "new_user").commit();
SharedPreferences newPref = this.getSharedPreferences("test", MODE_PRIVATE);
user = newPref.getString("user", default_user);
}
Ваш редактор записывает новую карту предпочтений на диск, но возможно, что старый SharedPreference
экземпляр не будет уведомлен об изменении.
Вместо использования
edit.commit();
вы должны использоватьedit.apply();
. Применить мгновенно обновит объект предпочтения и сохранит новый асинхронно, поэтому вы можете прочитать последние значения.
Источник - Также прочитайте подробное различие между commit()
и apply()
в этом сообщении SO.
Сообщение "Источник", упомянутое выше, также указывает на почти такую же проблему, и переход на apply()
, похоже, разрешил проблему там.
Заявление о проблемах в указанной статье:
Проблема в том, что когда я обращаюсь к этим значениям, это не возвращая обновленные значения, он дает мне значение SharedPreferences.
Но когда я подтверждаю данные в файле XML, данные обновляются в что.
PS: И причина того, что один и тот же блок кода не работает над этим одним приложением и работает со всеми другими приложениями, также может заключаться в том, что вы используете блок в разных местах или обновляете значение в другом месте.
Ваш код прав, код работает на любом приложении очень хорошо, похоже, что в какой-то части вашего приложения были изменены общие настройки, единственный способ найти решение - просмотреть весь ваш код, потому что если эта проблема происходит только в одном приложении, где-то в вашем приложении, что общие настройки были изменены, для хорошей практики вам должен быть только один класс файлов для управления вашими предпочтениями, чтобы вы могли комментировать или находить использование для метода, а вы может найти, где были изменены общие настройки.
BTW лучший способ сохранить пользователя, пароль или любую информацию об учетной записи использует Account Manager.
Для хороших практик вы можете увидеть этот пример класса PreferenceHelper.
public class PreferencesHelper {
public static final String DEFAULT_STRING_VALUE = "default_value";
/**
* Returns Editor to modify values of SharedPreferences
* @param context Application context
* @return editor instance
*/
private static Editor getEditor(Context context){
return getPreferences(context).edit();
}
/**
* Returns SharedPreferences object
* @param context Application context
* @return shared preferences instance
*/
private static SharedPreferences getPreferences(Context context){
String name = "YourAppPreferences";
return context.getSharedPreferences(name,
Context.MODE_PRIVATE);
}
/**
* Save a string on SharedPreferences
* @param tag tag
* @param value value
* @param context Application context
*/
public static void putString(String tag, String value, Context context) {
Editor editor = getEditor(context);
editor.putString(tag, value);
editor.commit();
}
/**
* Get a string value from SharedPreferences
* @param tag tag
* @param context Application context
* @return String value
*/
public static String getString(String tag, Context context) {
SharedPreferences sharedPreferences = getPreferences(context);
return sharedPreferences.getString(tag, DEFAULT_STRING_VALUE);
}}
Я использовал шаблон кода ниже в одном из моих приложений, и я всегда получаю последнее значение, хранящееся в SharedPreferences. Ниже приведена отредактированная версия для вашей проблемы:
public class AppPreference
implements
OnSharedPreferenceChangeListener {
private static final String USER = "User";
private static final String DEFAULT_USER = "Default_User";
private Context mContext;
private String mDefaultUser;
private SharedPreferences mPref;
private static AppPreference mInstance;
/**
* hide it.
*/
private AppPreference(Context context) {
mContext = context;
mPref = PreferenceManager.getDefaultSharedPreferences(context);
mPref.registerOnSharedPreferenceChangeListener(this);
reloadPreferences();
}
/**
* @param context
* @return single instance of shared preferences.
*/
public static AppPreference getInstance(Context context) {
return mInstance == null ?
(mInstance = new AppPreference(context)) :
mInstance;
}
/**
* @return value of default user
*/
public String getDefaultUser() {
return mDefaultUser;
}
/**
* Set value for default user
*/
public void setDefaultUser(String user) {
mDefaultUser = user;
mPref.edit().putString(USER, mDefaultUser).apply();
}
/**
* Reloads all values if preference values are changed.
*/
private void reloadPreferences() {
mDefaultUser = mPref.getString(USER, DEFAULT_USER);
// reload all your preferences value here
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
reloadPreferences();
}
}
Вы можете установить значение, указанное ниже в вашей деятельности:
AppPreference.getInstance(this).setDefaultUser("user_value");
Чтобы получить обновленное значение для сохраненного пользователя, используйте ниже код:
String user = AppPreference.getInstance(this).getDefaultUser();
Надеемся, что это решение решит проблему, с которой вы столкнулись.
Для сохранения и извлечения данных из SharedPrefrence создайте методы типа util в вашем классе Utility:
Ниже я дал фрагмент кода для обоих методов, например, для сохранения и получения данных SharedPrefrence:
public class Utility {
public static void putStringValueInSharedPreference(Context context, String key, String value) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(key, value);
editor.commit();
}
public static String getStringSharedPreference(Context context, String param) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(param, "");
}
}
Теперь вам просто нужно вызвать Utility.putStringValueInSharedPreference(Activity_Context, KEY, VALUE); помещать данные в prefrence и Utility.getStringSharedPreference(Activity_Context, KEY); чтобы получить выгоду от предчувствия. Эта методология уменьшает вероятность ошибки; Пусть это будет полезно для вас.
Я рекомендую контролировать вашу проверку предпочтений с другим значением предпочтения.
String user = pref.getString("user", default_user);
В вашей проверке предпочтений:
String getStatus = pref.getString("register", "nil");
if (getStatus.equals("true")) {
// move on code stuff
}
else{
// ask for preferences
}
В той части, где добавлено предпочтение.
edit.putString("user", "new_user");
editor.putString("register", "true");
edit.commit;
Не знаю, правильно это или нет, но вы можете реализовать прослушиватель Shared preference change, и вы можете войти в него и проверить, не вызвано ли общее предпочтение снова в любом другом классе, который снова устанавливает значение пользователю по умолчанию.
Я имею в виду, что вам нужно убедиться, что нет другого кода, который бы сбросил значение пользователя.
Сам код выглядит отлично, и вы говорите, что он работает в других приложениях. Поскольку вы подтвердили правильность создания XML файла, единственным оставшимся вариантом является то, что что-то происходит с файлом перед его чтением во время запуска приложения. Если в приложении нет других кодов, которые обрабатывают любые общие настройки, тогда что-то должно уничтожить файл во время запуска.
Вы должны внимательно изучить конфигурацию запуска этого конкретного приложения и сравнить с другими приложениями, где это работает. Возможно, есть некоторая опция, которая стирает пользовательские данные при запуске приложения. Я знаю, что есть такой вариант, по крайней мере, для эмулятора (в Eclipse), но я не уверен, что вы используете это в эмуляторе или устройстве.
Вы также должны попробовать запустить приложение непосредственно с устройства, а не с IDE. Это говорит о том, что проблема в самом приложении или конфигурации IDE. И попробуйте переместить это из onCreate (где я предполагаю, что это) на onResume и сравнить, работает ли оно, когда вы возобновляете приложение, и когда вы полностью перезапускаете его.