SharedPreferences 不保存强制关闭应用程序

Posted

技术标签:

【中文标题】SharedPreferences 不保存强制关闭应用程序【英文标题】:SharedPreferences doesn't save on force close app 【发布时间】:2013-03-08 15:42:59 【问题描述】:

我有一个带有复选框的登录表单,可以让应用记住LoginActivity 中的电子邮件。如果我按下登录按钮,则电子邮件应使用 AppPreferences 类存储在 SharedPreferences 中。

如果我通过按主页按钮并按返回返回主屏幕,应用程序会记住电子邮件。

但如果我强制关闭应用程序会显示Preferencemanager.getString("value", "default_value"); 方法中定义的默认值。

我已经尝试了很多人们在 SO 上提出的建议,但不幸的是,没有一个解决方案奏效。我什至试图通过将所有 SharedPreferences 代码放在一个单独的类中来解决它(参见 this question)。

下面我放了与问题相关的尽可能多的代码。所以LoginActivityAppPreferences 这两个类。 LogCat 没有给出错误消息。

在装有 android 4.2.2 Cyanogenmod 10.1 和几个不同模拟器的三星设备 I9100 和 P3110 上都会出现此问题。 (我读到一些带有 HoneyComb 的三星 S 设备无法正确保存 SharedPreferences?)


编辑: 正如我忘记提到的,该项目针对 API 17 和 minSdkVersion = 11。我只在单击登录按钮时保存凭据。编辑 2: 如果手机重启,也会出现此问题


LoginActivity 类:

public class LoginActivity extends Activity

    private static final String PREF_REMEMBER_EMAIL = "LoginCredentialsRememberEmail";
    private static final String PREF_EMAIL = "LoginCredentialsEmail";

    private String mEmail;

    private EditText mEmailView;
    private CheckBox cbRememberEmail;   

    private AppPreferences appPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        appPreferences = new AppPreferences(LoginActivity.this);

        loadUserCredentials();
    
    @Override
  protected void onResume()        
        super.onResume();
        loadUserCredentials();
    

    @Override
    protected void onStart() 
        super.onStart();
        loadUserCredentials();
    

    private void loadUserCredentials() 
        String rememberEmail = appPreferences.getPreferenceString(PREF_REMEMBER_EMAIL);
        String email = appPreferences.getPreferenceString(PREF_EMAIL);
        mEmailView = (EditText) findViewById(R.id.email);
        mEmailView.setText((rememberEmail == "1") ? email : "");
        cbRememberEmail = (CheckBox) findViewById(R.id.cbRememberEmail);
        cbRememberEmail.setChecked(rememberEmail == "1" ? true : false);
        mEmail = mPassword = "";
    
    private void saveUserCredentials()         
        try 
        String rememberemail = (((CheckBox) findViewById(R.id.cbRememberEmail)).isChecked()) ? "1" : "0";
        appPreferences.setPreferenceString(PREF_REMEMBER_EMAIL, rememberemail);
        String email = (rememberemail == "1") ? mEmail : "";
        appPreferences.setPreferenceString(PREF_EMAIL, email);
    



    public void cbRememberEmailClick(View view) 
        boolean checked = ((CheckBox) findViewById(R.id.cbRememberEmail)).isChecked();
        if (checked) 
            new AlertDialog.Builder(this).setTitle(R.string.remember_email_notification_title).setMessage(R.string.remember_email_notification_message).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int which) 
                    ((CheckBox) findViewById(R.id.cbRememberEmail)).setChecked(true);
                
            ).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int which) 
                    ((CheckBox) findViewById(R.id.cbRememberEmail)).setChecked(false);
                
            ).show();
        
    
// ...

AppPreferences 类:

public class AppPreferences 
    Context context;

    private SharedPreferences settings = null;

    private static String LOGIN_CREDENTIALS = "com.example.login.credentials";
    private static String DEFAULT_STRING = "";

    public AppPreferences(Context context) 
        this.context = context;
        settings = PreferenceManager.getDefaultSharedPreferences(context);
    

    private String getKey(String key) 
        return LOGIN_CREDENTIALS + "." + key;
    

    public String getPreferenceString(String key) 
        return settings.getString(getKey(key), DEFAULT_STRING);
    
    public void setPreferenceString(String key, String value) throws Exception 
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(getKey(key), (String) value);
        editor.commit();
    
// ...

非常感谢任何帮助,我被困了好几天,现在真的很沮丧。

提前致谢。

敬业

【问题讨论】:

【参考方案1】:

您没有显示调用saveUserCredentials 的代码。你应该打电话给onPause

@Override
protected void onPause() 
    super.onPause();
    saveUserCredentials();

如果你在后面的生命周期方法之一中调用它(例如onDestroy),如果应用程序在后台被强制关闭,它将不会被调用。 (如果您仅针对 Honeycomb 及更高版本,则可以将此推迟到 onStop。)

【讨论】:

我可能错了,但如果你强制关闭应用程序,onPause 或 OnDestory 将不会执行,因为它会完全杀死进程并且任何代码执行都没有完成 @Boardy - 如果您强制关闭前台应用程序,那么您无法保证数据被保存。 (您可以使用 adb 强制关闭前台应用程序,但很难看出如何在设备本身上执行此操作。)如果活动不在前台,则将调用 onPause 方法(并且通话完成)。强制关闭会跳过 onStop(Honeycomb 之前)和 onDestroy 方法调用。 感谢您的输入,但正如我所提到的,如果单击登录按钮,我只会保存电子邮件。很抱歉我忘记了saveUserCredentials,这个方法在cbRememberEmailClick 中调用。目标是 API 17 (Honeycomb) 和 minSdkVersion = 11【参考方案2】:

我推荐你,把 save 方法放到 onDestroy 方法中

【讨论】:

onDestroy 在后台应用被强制关闭时不会被调用。 我只想在点击登录按钮时保存凭据【参考方案3】:

我通过将字段 rememberEmail 更改为 Boolean 而不是包含 10 的字符串来修复它。我不知道为什么这不起作用,但我更高兴的是,经过 11 天的挫折之后,这不再是问题了。

我还删除了文件夹/data/data/com.example/shared_prefs/中的所有首选项文件

LoginActivity中的代码已更改

// ....
private void loadUserCredentials() 
    Boolean rememberEmail = appPreferences.getPreferenceBoolean(PREF_REMEMBER_EMAIL);
    String email = appPreferences.getPreferenceString(PREF_EMAIL);
    mEmailView = (EditText) findViewById(R.id.email);
    mEmailView.setText(rememberEmail ? email : "");
    cbRememberEmail = (CheckBox) findViewById(R.id.cbRememberEmail);
    cbRememberEmail.setChecked(rememberEmail);

private void saveUserCredentials()         
    try 
    Boolean rememberEmail = ((CheckBox) findViewById(R.id.cbRememberEmail)).isChecked();
    appPreferences.setPreferenceBoolean(PREF_REMEMBER_EMAIL, rememberEmail);
    String email = (rememberEmail) ? mEmail : "";
    appPreferences.setPreferenceString(PREF_EMAIL, email);

// ....

AppPreferences

// ....
private String getKey(String key) 
    key = key.toLowerCase();
    return LOGIN_CREDENTIALS + "." + key;

// newly added methods below
public String getPreferenceBoolean(String key) 
    return settings.getBoolean(getKey(key), DEFAULT_BOOLEAN);

public void setPreferenceBoolean(String key, Boolean value) throws Exception 
    SharedPreferences.Editor editor = settings.edit();
    editor.putBoolean(getKey(key), (Boolean) value);
    editor.commit();

// ....

希望你不会犯和我一样的错误;)

【讨论】:

【参考方案4】:

如果您在选中复选框时调用saveUserCredentials();,这应该可以正常工作。还可以尝试在应用程序启动时初始化首选项 obj

【讨论】:

每当单击登录按钮时,我都会调用saveUserCredentials(),这对我来说似乎更符合逻辑。但是,如果我强制关闭应用程序或重新启动设备,则不会保存任何内容..

以上是关于SharedPreferences 不保存强制关闭应用程序的主要内容,如果未能解决你的问题,请参考以下文章

将 ArrayList 保存到 SharedPreferences

SharedPreferences 不保存布尔属性

默认 SharedPreferences 不保存值

SharedPreferences 将按钮更改保存为单击后不可见

SharedPreferences存储数据

SharedPreferences保存字符串[重复]