Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will SharedPreferences "commit()" be automatically changed to "apply()" in Androids code optimization?

So, I'm facing this weird problem right now. I HAVE to use SharedPreferences.Editor().commit() in my Android app, but, as the documentation here states,

As SharedPreferences instances are singletons within a process, it's safe to replace any instance of commit() with apply() if you were already ignoring the return value.

You don't need to worry about Android component lifecycles and their interaction with apply() writing to disk. The framework makes sure in-flight disk writes from apply() complete before switching states.

Basically it is safe to replace commit() with apply() if you're not using the return value, BUT, the difference between two as mentioned here, and as warning in Android Studio states, is that commit() immediately writes the data, BUT apply() does that asynchronously.

So my problem here is, I'm changing the language in my app, and I want to restart my app after user chooses the language. But, when user chooses the language, the current chosen language is put in SharedPreferences.

Now, the problem:

Whenever I use apply() instead of commit() and restart my app using the code to restart the app here, the changes are not written on the disk, as, when the app restarts, it does not change the current language, as the value from SharedPreference is not changed, because it is not immediately written on the disk. But, whenever I use commit(), the changes are immediately written, and the language is successfully changed when the app is restarted.

So, the questions:

  1. How can people who wrote the code for commit() and apply() say that it is completely safe to use apply() instead of commit(), if there's very big difference, as commit() writes the data immediately, but apply() does it in background?

  2. If I build my apk, will the commit() be replaced by apply() in code optimization if I'm not using the return value.(I know I can know this by building the release version of the app, but I still won't be sure, because when I use apply(), it veeery frequently 1/10 times actually does change the value from SharedPreference)

A note:

  1. I know how I can use Apply() and still make my app work, maybe I'll have to add some delay before restarting the app? But I'm not sure how it'll work as it'll still take some time to actually write the data on disk, and I don't currently see any method to check if the SharedPreference value was actually changed, so that I can safely restart AFTER the value was changed.
like image 930
Vedprakash Wagh Avatar asked Jun 24 '19 14:06

Vedprakash Wagh


1 Answers

The problem is, that with Runtime.getRuntime().exit(0) or System.exit(0) you'll kill the process and therefore no scheduled async task will execute after.

If you don't intend to change your restart code, you should keep commit instead of apply for this instance and suppress the warning.

  1. It's safe to assume that the statement is valid, because calling exit(0) is an edge-case you should not do normally.
  2. There's no reason to assume that commit will be replaced with apply automatically. If you want to make sure of it, just use the return value.
like image 145
tynn Avatar answered Oct 04 '22 22:10

tynn