I am agreeing with @Victor Pozdnyakov answer. So, I won't reiterate here that, but I really struggled to get that working in java just for saving a single value; I didn't find any tuts on that, so I had to dig into RxJava
documentation.
Here an example to store an int value and return it without continuous data observation (just like you do with SharedPreferences
)
Dependencies:
implementation "androidx.datastore:datastore-preferences:1.0.0"
// RxJava3 support
implementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
The example provided with describing comments:
public class MainActivity extends AppCompatActivity {
// Data store object
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(this, "settings").build();
// Key for saving integer value
Preferences.Key<Integer> SOME_KEY = PreferencesKeys.intKey("SOME_KEY");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Storing an int value to DataStore with the key of SOME_KEY
saveInt(SOME_KEY, 1050);
// Read the data immediately as it's already observed
observeInt(SOME_KEY, value -> runOnUiThread(() ->
Toast.makeText(this, "Observed Value: " + value, Toast.LENGTH_SHORT).show()));
// Wait some time before reading the data as it takes time until it's stored;
// so don't call it here, but on some other event
readInt(SOME_KEY, value -> runOnUiThread(() ->
Toast.makeText(this, "Value: " + value, Toast.LENGTH_SHORT).show()));
}
/**
* Saving an int value to DataStore with some key
*
* @param key: The key associated to the value need to be stored
* @param value: The value to be stored
*/
private void saveInt(Preferences.Key<Integer> key, int value) {
dataStore.updateDataAsync(prefsIn -> {
MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
mutablePreferences.set(key, value);
return Single.just(mutablePreferences);
}).subscribe();
}
/**
* Returning an int value from the DataStore which is associated to some key,
* once the result is returned, the subscription is disposed.
*
* @param key: The key associated to the value need to be stored
* @param listener: The value is returned in a worker thread, and returned to the
* caller using a listener pattern
*/
public void readInt(Preferences.Key<Integer> key, IntListener listener) {
Flowable<Integer> flowable =
dataStore.data().map(prefs -> prefs.get(key));
flowable.firstOrError().subscribeWith(new DisposableSingleObserver<Integer>() {
@Override
public void onSuccess(@NotNull Integer value) {
listener.intValue(value);
}
@Override
public void onError(@NotNull Throwable error) {
error.printStackTrace();
}
}).dispose();
}
/**
* Subscribing an observer to an int value in the DataStore which is associated to some key,
* The subscription submits any change to the value
*
* @param key: The key associated to the value need to be stored
* @param listener: The value is returned in a worker thread, and returned to the
* caller using a listener pattern
*/
public void observeInt(Preferences.Key<Integer> key, IntListener listener) {
Flowable<Integer> flowable =
dataStore.data().map(prefs -> prefs.get(key));
flowable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) // AndroidSchedulers requires ` implementation "io.reactivex.rxjava3:rxandroid:3.0.0" `
.subscribe(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(@NonNull Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Integer value) {
listener.intValue(value);
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onComplete() {
}
});
}
interface IntListener {
void intValue(int value);
}
}