You probably noticed that I added different data types on the screen. Here is another catch: if you want to keep the type of your data from DataStore
consistent with the Settings screen, you also need to do extra things.
Out of the box, the Preferences library provides several types of UI elements for selecting preferences: EditTextPreference
, ListPreference
, SwitchPreferenceCompat
, and so on. I’m willing to bet that the most popular ones are Switch and List! In the case of SwitchPreference
, it’s expected that it persists a value of Boolean type, but ListPreference
works only with String arrays.
Imagine that you have a video app where the user can choose the playback speed for a video. You have a predefined set of values for this feature. For example:
val playbackSpeed = mapOf(
"0,5x" to 0.5f,
"1x" to 1.0f,
"1,5x" to 1.5f,
"2x" to 2.0f
)
The playback speed is represented with a float value because the video player works with this type. You have already used DataStore
to persist the last used playback speed, but you want to allow users to choose their preferred playback speed from your Settings screen. If you built it using the Preferences library, you have a problem because you can’t use the common ListPreference
for this. You’ll just get a ClassCastException
.
Of course, you can keep all your preferences as strings and cast them to the type you need; it’s up to you. But there is another way. We can delegate this work to a custom ListPreference
that handles all these tasks under the hood and persists values in the specified type. To represent all possible data types, I created an abstract class to reduce the amount of code for each of its inheritors:
And here is an example of a custom ListPreference
for float data:
Its usage in UserPreferencesFragment
: