SharedPreferences总是在我现有的应用程序中获得默认值,但是在创建新应用程序时它就可以了

时间:2016-01-08 12:16:13

标签: android sharedpreferences

SharedPreferences在一个现有应用中无法正常工作。我尝试了很多不同的方法,但仍然没有工作。始终再次启动默认值app。

  • 当我在创建的新应用中使用相同的代码时,它正在工作。
  • 它正在处理所有其他现有应用。

你知道为什么吗?

    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

11 个答案:

答案 0 :(得分:8)

当您致电apply()commit()时,更改会首先保存到应用的内存缓存中,然后Android会尝试将这些更改写入磁盘。这里发生的事情是您的commit()调用在磁盘上失败,但仍然对应用程序的内存缓存进行了更改,如source中所示。

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

您未能做的是检查commit()调用返回的布尔值,对于您的问题情况可能是错误的。如果返回false,您可以重试commit()次呼叫几次。

答案 1 :(得分:8)

只需使用以下方法并检查。

创建一个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();

现在用userName做任何事情。

经常检查

if(userName.trim().isEmpty())
{
    // Do anything here.
}

因为在SharedPreferences我们将用户名设置为空(“”)

您可以在SharedPreferences中设置用户名为null,然后您需要检查

if(userName != null){
    //do anything here
}

来自SharedPreferences清除数据。

AppTypeDetails.getInstance(MainActivity.this).setUser("");

AppTypeDetails.getInstance(MainActivity.this).clear();

答案 2 :(得分:4)

您可以尝试的一件事是在提交后获得一个新的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实例可能不会通知更改。

答案 3 :(得分:4)

  

您应该使用edit.commit();而不是edit.apply();应用   会立即更新偏好设置并保存新内容   值异步,因此允许您读取最新值。

Source - 同时阅读此SO帖子中commit()apply()之间的详细差异。

&#34;来源&#34;上面提到的帖子也说明了几乎相同的问题,切换到apply()似乎解决了那里的问题。

引用帖子中的问题陈述:

  

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

     

但是当我确认XML文件中的数据时,数据已更新   这一点。

PS:并且相同的代码块不能在这个应用程序上工作并且在所有其他应用程序上工作的原因也可能是您要么在不同的地方使用块,要么在其他地方更新值。

答案 4 :(得分:4)

您的代码是正确的,代码可以很好地适用于任何应用程序,在应用程序的某些部分看起来已经修改了共享首选项,找到解决方案的唯一方法是查看所有代码,因为如果这个问题只发生在一个应用程序上,它在您的应用程序的某个地方已经修改了共享首选项,对于良好实践,您应该只有一个文件类来管理您的首选项,您可以通过这种方式评论或查找用法方法,您可以找到共享首选项的修改位置。

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

答案 5 :(得分:2)

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

(begin1, end1)

您可以在活动中设置以下值:

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

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

答案 6 :(得分:1)

要从SharedPrefrence保存和检索数据,请在Utility类中创建一个util类型方法:

下面我给出了两种方法的代码片段,即保存和检索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);从prefrence获得价值。 这种方法减少了出错的可能性;愿这对你有所帮助。

答案 7 :(得分:1)

我建议使用其他偏好值控制您的偏好检查。

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;

在添加首选项的部分。

fwrite($pipes[0], "$cmd \n");   
stream_set_timeout($pipes[1], 20);
$read = fread($pipes[1], 2096) . "\n";

答案 8 :(得分:1)

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

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

答案 9 :(得分:1)

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

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

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

答案 10 :(得分:0)

最后我解决了这个问题。 其他开发人员之一添加了一种方法。 此方法正在删除除libs文件夹之外的data / data / packageName文件夹下的所有文件。 我认为他们尝试删除缓存文件夹。

删除了这个方法并解决了。