GCX-HCI / tray

a SharedPreferences replacement for Android with multiprocess support
Apache License 2.0
2.29k stars 273 forks source link

changeVersion doesn't support multithreading. -> NullPointerException #96

Open toy-lin opened 7 years ago

toy-lin commented 7 years ago

Very thanks for your product,but i have got a NullPointerException while migrating data,can anybody give me some advice?

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference at net.grandcentrix.tray.core.SharedPreferencesImport.onPostMigrate(SharedPreferencesImport.java:79) at net.grandcentrix.tray.core.SharedPreferencesImport.onPostMigrate(SharedPreferencesImport.java:38) at net.grandcentrix.tray.core.Preferences.migrate(Preferences.java:125) at ...module.sp.CookiePreferences.importSP(CookiePreferences.java:47) at ...module.sp.CookiePreferences.onCreate(CookiePreferences.java:29) at net.grandcentrix.tray.core.Preferences.changeVersion(Preferences.java:262) at net.grandcentrix.tray.core.Preferences.isVersionChangeChecked(Preferences.java:292) at net.grandcentrix.tray.core.Preferences.(Preferences.java:58) at net.grandcentrix.tray.core.AbstractTrayPreference.(AbstractTrayPreference.java:31) at net.grandcentrix.tray.TrayPreferences.(TrayPreferences.java:43) at net.grandcentrix.tray.TrayPreferences.(TrayPreferences.java:48) at ..*.module.sp.CookiePreferences.(CookiePreferences.java:23)

And below is code in CookiePreferences:

`public class CookiePreferences extends TrayPreferences { private static final String TAG = CookiePreferences.class.getSimpleName(); public static final String MODULE = "cookie"; private static final String SP_NAME = "mycookie"; public CookiePreferences(Context context) { super(context, MODULE, 1); }

@Override
protected void onCreate(int initialVersion) {
    super.onCreate(initialVersion);
    importSP();
}

private void importSP() {
    final SharedPreferences sps = getContext().getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
    HashMap<String, Object> all = new HashMap<>(sps.getAll());

    Set<Map.Entry<String, Object>> set = all.entrySet();
    for (Map.Entry<String, Object> en : set) {
        String key = en.getKey();
        SharedPreferencesImport ip = new SharedPreferencesImport(getContext(), SP_NAME, key, key);
        migrate(ip);
    }
}

}`

Version:

compile 'net.grandcentrix.tray:tray:0.11.1'

toy-lin commented 7 years ago

Oh, i have found the problem.I thought Tray is thread safe but it's not. In my case ,method 'onCreate' was invoked twice from different thread. Am i wrong with my code?

toy-lin commented 7 years ago

Yes,Tray isn't thread safe.The lock to check version change is a TrayPreferences object, so if we create more than one TrayPreferences object in different thread , method 'onCreate' would probably be invoked more than 1 time. "synchronized void changeVersion(final int newVersion)"

passsy commented 7 years ago

Good finding. We will fix that

bdelville commented 5 years ago

The same problem would happen in onCreate if multiple process start at the same time