Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SharedPreferences always get default value in my existing app but when created new app its ok

SharedPreferences doesn't work correct in one existing apps. I tried many different ways but still not working. Always get default values app start again.

  • It's working when I use same code in created new app.
  • It's working all of other existing apps.

Do you know why?

    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: log results

that block always return this for which is incorrect app and I don't know why

    //first run
    SHARED CHECK Default_User
    SHARED WRITE new_user

    //each time after first
    SHARED CHECK Default_User
    SHARED WRITE new_user

That block always return this for which are all apps

    //first run
    SHARED CHECK Default_User
    SHARED WRITE new_user

    //each time after first
    SHARED CHECK new_user
    SHARED READ new_user
like image 996
Kaloglu Avatar asked Jan 08 '16 12:01

Kaloglu


4 Answers

When you call apply() or commit() the changes are first saved to the app's memory cache and then Android attempts to write those changes onto the disk. What is happening here is that your commit() call is failing on the disk but the changes are still made to the app's memory cache, as is visible in the source.

It is not enough to read the value from the SharedPreferences as that value might not reflect the true value that is on the disk but only that stored in the memory cache.

What you are failing to do is to check the boolean value returned from the commit() call, it is probably false for your problematic case. You could retry the commit() call a couple of times if false is returned.

like image 110
Ernir Erlingsson Avatar answered Nov 15 '22 18:11

Ernir Erlingsson


Just use below method and check.

Create one Java class 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();
    }
}

Now Set value to SharedPreferences.

AppTypeDetails.getInstance(MainActivity.this).setUser(<user name>);

Get Value form SharedPreferences.

String userName = AppTypeDetails.getInstance(MainActivity.this).getUser();

Now do any thing with the userName.

Always check

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

because In SharedPreferences we set user name blank ("")

or

you can set user name null in SharedPreferences then you need check

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

For clear data from SharedPreferences.

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

or

AppTypeDetails.getInstance(MainActivity.this).clear();
like image 23
Chirag Savsani Avatar answered Nov 15 '22 16:11

Chirag Savsani


One thing you could try is to get a new SharedPreference instance after committing and see what happens:

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

Your editor is committing a new preference map into disk, but it is possible that the old SharedPreference instance is not notified of the change.

like image 42
natario Avatar answered Nov 15 '22 18:11

natario


Instead of using edit.commit();, you should use edit.apply();. Apply will update the preference object instantly and will save the new values asynchronously, so allowing you to read the latest values.

Source - Also read detailed difference between commit() and apply() in this SO Post.

The "Source" post referenced above also states pretty much the same problem and switching to apply() seems to have resolved the issue there.

Problem statement in the referenced post:

The problem is that when I am accessing this values, it is not returning updated values, it gives me a value of SharedPreferences.

But when I am confirming the data in XML file ,the data updated in that.

PS: And the reason that the same code block is not working on this one app and working on all other apps could also be that you are either using the block at different places or updating the value somewhere else too.

like image 28
AndroidMechanic - Viral Patel Avatar answered Nov 15 '22 18:11

AndroidMechanic - Viral Patel