Is SharedPreferences a safe way of sharing settings between a service and the UI?

90 views Asked by At

Is SharedPreferences a safe way of sharing settings between a service and the UI?

I am calling commit() in a service and when I read the prefs in the UI 300ms later, the data is not there. This is on API 27.

I already use the Messenger for communicating between the service and the UI.

This is how I'm storing data on the services side:

  local e = context:getSharedPreferences("characters", context.MODE_PRIVATE):edit()
  e:putString("list", table.concat(names, "|"))
  log("saved these names in characters: %s", tstring(names))
  e:commit()
  local stuff = context:getSharedPreferences("characters", context.MODE_PRIVATE)

Retrieving it in the UI:

  charlist_settings = activity:getSharedPreferences("characters", activity.MODE_PRIVATE)
  log("refreshlist hit")
  if charlist_settings:contains("list") and charlist_settings:getString("list", "") ~= "" then
    [...]
  else
    log("no list in char_settings :(")
    log("all: %s", charlist_settings:getAll():toString())
  end

Service log, notice timestamp:

12-22 18:56:30.246 4142-4142/org.vadisystems.irehelper:Service I/IRE Helper: modified is: added
12-22 18:56:30.253 4142-4142/org.vadisystems.irehelper:Service I/IRE Helper: saved these names in characters: {"Vadimuses_Achaea"}

UI log, this is after a message is received from the service:

12-22 18:56:30.700 4120-4120/org.vadisystems.irehelper I/IRE Helper: refreshlist hit
12-22 18:56:30.701 4120-4120/org.vadisystems.irehelper I/IRE Helper: no list in char_settings :(
12-22 18:56:30.702 4120-4120/org.vadisystems.irehelper I/IRE Helper: all: {}
3

There are 3 answers

1
Vadim Peretokin On BEST ANSWER

Not even restarting the activity worked to get the data after it has been commited. The only thing that did was restarting the application entirely. This was on API 27.

18
jugutier On

Use a local broadcast receiver, when the action is done, broadcast. On the listen side you have a class that takes care of persisting to SharedPreferences and also the UI can have a separate listener and update itself.

Sample Kotlin code

[EDIT] After suggesting using apply vs commit as a quick workaround relying on a in-memory cache layer that turned out not to be provided by SharedPreferences we are adjusting this answer to use a Local Broadcast receiver instead.

2
Steve M On

This should work, using either commit() or apply() based on the documentation. The change should be visible immediately between all in-process threads and components. However I have noted bugs in Android trying to do this between a Service and Activity in the past. Having you tried using getDefaultSharedPreferences() instead of a custom file. I have had no problems using the default file.