LibGDX, Preferences, and Android

Another day of coding with LibGDX, another annoying Android issue.

This time, it involves a Preferences object. I have a settings menu where the user can adjust things like sound effects volume, etc. There is a single Preferences object that lasts the entire lifetime of the game. In the settings menu, I read from and write to this object. And obviously I read the values elsewhere for the settings to take effect.

A Preferences object is a simple key/value store with a "flush" method for persistence. Great, I figure. I can write to this thing, read from it, and persist it when needed. So, my approach to the settings menu is for the widget callback to write values to the persistence object. I.e., when a slider is slid, the callback grabs the new value of the slider. It then assigns this value to the relevant key in the preferences object. Then, any runtime state that needs realtime updating (e.g. music volume) can pick up these changes in their normal processing by reading the preferences object. When the user exits the settings menu, the values are persisted with the flush() method.

This approach works fine on desktop builds, but not on Android. Consider this minimal example:


prefs.putFloat("foo", 5.0f);
y = prefs.getFloat("foo");

You might think the value of y should be 5.0f. On desktop builds, this is the case. But on Android, nope. It's whatever the value was last time it was loaded or flushed. Apparently, the Android implementation has separate memory regions for reading and writing which are not reconciled until flush().

The quick and dirty fix is to flush after every prefs.putFoo() call.


prefs.putFloat("foo", 5.0f);
prefs.flush();
y = prefs.getFloat("foo");

(Of course in actual code, the prefs.getFloat() call is not going to be immediately after the flush, but later on in some section of code that needs the value of "foo".)

For the settings menu, this approach seems needlessly inefficient - the preferences are repeatedly written to storage while the slider is being slid.

The other obvious approaches would seem to be:

1. Push updates directly to the realtime components that need updating rather than letting them pick them up from the prefs object.

2. Create a separate object that is authoritative for this data, and use the Preferences object solely as a means of persisting the data.

The former is easier to implement given a small number of settings, but the latter seems architecturally cleaner and more easily maintained once it's working.

Comments

Popular posts from this blog

Skastic: An image-based esoteric programming language

Fixing sound effects issues in LibGDX on Android