Android SharedReferences总是在我现有的应用程序中获得默认值,但在创建新应用程序时,它是ok的

Android SharedReferences总是在我现有的应用程序中获得默认值,但在创建新应用程序时,它是ok的,android,sharedpreferences,Android,Sharedpreferences,SharedReferences在现有应用程序中无法正常工作。我尝试了许多不同的方法,但仍然不起作用。始终获取默认值应用程序重新启动 当我在创建的新应用程序中使用相同的代码时,它就起作用了 它正在运行所有其他现有的应用程序 你知道为什么吗 String default_user = "Default_User"; SharedPreferences pref = this.getSharedPreferences("TEST_SHAREDPREF", MODE_PRIVATE

SharedReferences在现有应用程序中无法正常工作。我尝试了许多不同的方法,但仍然不起作用。始终获取默认值应用程序重新启动

  • 当我在创建的新应用程序中使用相同的代码时,它就起作用了
  • 它正在运行所有其他现有的应用程序
你知道为什么吗

    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();
    }
编辑:记录结果

那个块总是返回这是不正确的应用程序,我不知道为什么

    //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
当您调用
apply()
commit()
时,更改首先保存到应用程序的内存缓存中,然后Android会尝试将这些更改写入磁盘。此处发生的情况是,您的
commit()
调用在磁盘上失败,但仍会对应用程序的内存缓存进行更改,如图中所示

从SharedReferences读取值是不够的,因为该值可能不反映磁盘上的真实值,而只反映存储在内存缓存中的值


您没有做的是检查从
commit()
调用返回的布尔值,对于有问题的情况,它可能是false。如果返回false,您可以重试几次
commit()
调用

您可以尝试的一件事是在提交后获取一个新的
SharedReference
实例,看看会发生什么:

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);
}

您的编辑器正在将新的首选项映射提交到磁盘中,但旧的
SharedReference
实例可能没有收到更改通知。

只需使用下面的方法并进行检查

创建一个
Java
classAppTypeDetails.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();
    }
}
现在值设置为
SharedReferences

AppTypeDetails.getInstance(MainActivity.this).setUser(<user name>);
String userName = AppTypeDetails.getInstance(MainActivity.this).getUser();
AppTypeDetails.getInstance(MainActivity.this).setUser("");
现在用用户名做任何事情

经常检查

if(userName.trim().isEmpty())
{
    // Do anything here.
}
因为在
SharedReferences
中,我们将用户名设置为空(“”)

您可以在
SharedReferences
中将用户名设置为null,然后需要进行检查

if(userName != null){
    //do anything here
}
对于清除
SharedReferences
中的数据

AppTypeDetails.getInstance(MainActivity.this).setUser(<user name>);
String userName = AppTypeDetails.getInstance(MainActivity.this).getUser();
AppTypeDetails.getInstance(MainActivity.this).setUser("");


要从SharedReference保存和检索数据,请在实用程序类中创建util类型的方法:

下面我给出了这两种方法的代码片段,即用于保存和检索SharedReference数据的代码片段:

   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(活动\上下文、键、值);将数据放入prefrence和Utility.getStringSharedReference(活动上下文,键);从prefrence获取值。
这种方法减少了出错的机会;这可能会对您有所帮助。

我建议您使用另一个首选项值来控制您的首选项检查

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;
而不是使用
edit.commit()
,您应该使用
edit.apply()应用
将立即更新首选项对象,并保存新对象
异步读取值,因此允许您读取最新的值

-还请阅读本文中
commit()
apply()
之间的详细区别

上面提到的“Source”帖子也说明了几乎相同的问题,切换到
apply()
似乎已经解决了这个问题

引用帖子中的问题陈述:

问题是,当我访问这个值时,它不是 返回更新后的值,它会给我一个SharedReferences值

但是当我确认XML文件中的数据时,数据在 那就是。


PS:同一代码块不能在这一个应用程序上运行,也不能在所有其他应用程序上运行的原因可能是,您在不同的地方使用了该代码块,或者在其他地方更新了值。

我在我的一个应用程序中使用了下面的代码模式,并且我总是在SharedReferences中存储最新的值。以下是针对您的问题编辑的版本:

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();

希望此解决方案能解决您面临的问题。

不知道这是否正确,但您可以实现共享首选项更改侦听器,您可以登录该侦听器并检查是否在任何其他类中再次调用共享首选项,该类再次将值设置为默认用户


我的意思是,你必须确保没有其他代码重置用户的值。

代码本身看起来很好,你说它在其他应用程序中也有效。由于您已确认XML文件已正确创建,因此唯一剩下的选项是,在应用程序启动期间读取文件之前,该文件会发生某些情况。如果应用程序中没有处理任何共享首选项的其他代码,则必须在启动期间清除文件

您应该仔细查看此特定应用程序的启动配置,并将其与其他应用程序进行比较。也许有一些选项可以在应用程序启动时擦除用户数据。我知道至少emulator(在Eclipse中)有这样一个选项,但我不确定您是在emulator还是在设备中运行这个选项


您还应该尝试直接从设备而不是IDE启动应用程序。这说明问题是在应用程序本身还是IDE配置中。然后试着将它从onCreate(我猜是这样)移动到onResume,比较你恢复到应用程序时与完全重新启动应用程序时是否有效。

你的代码是正确的,代码在任何应用程序上都工作得很好,看起来在你的应用程序的某些部分,共享首选项被修改了,找到解决方案的唯一方法是查看您的所有代码,因为如果此问题只发生在一个应用程序上,则共享首选项会在应用程序的某个位置被修改,