While working with a web API I noticed the main shortcomings for apply() when using shared preferences before logging out.
Behold the following scenario:
User logs in and token (for automatic relogging) was passed with the POST.
SharedPreferences preferences = App.getContext().getSharedPreferences("UserCredentials", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("TOKEN",token);
editor.apply();
Token is available throughout all sessions, no problem and automatic relogging is done without any further problems throughout the states.
While writing the logout function I cleared the shared preferences as follows
SharedPreferences preferences = App.getContext().getSharedPreferences("UserCredentials", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.clear();
editor.apply()
In short you could simply write as:
preferences.edit().clear().apply()
To make sure I cleared the cache I would Log before logging out, and preferences.getString("TOKEN");
showed as null
.
After restarting the main activity (as it started with a login fragment) - I would check the token again, using:
SharedPreferences preferences = App.getContext().getSharedPreferences("UserCredentials", MODE_PRIVATE);
String retrievedToken = preferences.getString("TOKEN",null); // Second param = default value
Log.d(TAG, "RETRIEVING TOKEN: " + retrievedToken);
The token actually re-appeared, even though the token was most certainly cleared before logging out.
(Causing a logout -> 'login-using-token loop)
Only after adding editor.commit();
to both setting and clearing the token would actually be permanently gone.
Do note, I used an emulator.
This behavior actually makes sence, as the in-memory storage is updated but the async call never made it before the app was restarted.
Therefor commit();
would FORCE the app to wait (synchronously) with actual subsequent commands like system.exit()
etcetera, while apply()
could very well fail if other commands would force a certain state change in the app.
To make sure you hit all the right spots, you can always use apply() & commit() both subsequently.
apply()
will asynchronously do disk I/O whilecommit()
is synchronous. So you really shouldn't callcommit()
from the UI thread. – Spodeapply()
wins. Therefore, you can useapply()
in lieu ofcommit()
safely if you make sure only one SharedPreferences.Editor is being used by your application. – Milamiladycommit()
? – Saberio