#java #android #kotlin #android-jetpack #android-jetpack-datastore
#java #Android #kotlin #android-jetpack #android-jetpack-хранилище данных
Вопрос:
Я читал о новой библиотеке из Jetpack (теперь в альфа-версии) — хранилище данных Jetpack.
Из документации ясно, что это своего рода Shared Preferences' killer
Хранилище данных Jetpack — это решение для хранения данных, которое позволяет хранить пары ключ-значение или типизированные объекты с буферами протокола
Хранилище данных использует сопрограммы Kotlin и Flow для хранения данных асинхронно, последовательно и транзакционно
Если в настоящее время вы используете SharedPreferences для хранения данных, рассмотрите возможность перехода на хранилище данных
Если я ничего не упущу, вы не сможете использовать эту библиотеку в Java. Я прав? Лично я использую Kotlin, но для меня это своеобразный прецедент для библиотеки AndroidX.
Ответ №1:
Вы можете использовать хранилище данных только в RxJava. В обычной java теперь вы можете использовать только SharedPreferences. Давайте сравним настройки хранилища данных RxJava с SharedPreferences
1) доступ
Хранилище данных:
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();
SharedPreferences:
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
2) прочитайте:
Хранилище данных: определите ключ для вашего значения (в примере для значения int), а затем получите доступ к данным хранилища данных: PreferencesKeys.int («example_counter»)
data()
— доступ к данным хранилища данных. Это свойство возвращает поток
map()
— возвращает поток, содержащий результаты применения данной функции к каждому значению исходного потока
SharedPreferences
SharedPref.getInt(«highScoreKey», 0);
Чтобы получить значения из общего файла настроек, укажите ключ для нужного значения со значением по умолчанию (o здесь в примере)
3) напишите
Хранилище данных:
транзакционное обновление данных в хранилище данных
SharedPreferences:
Использование SharedPreferences.Редактор передайте ключи и значения, которые вы хотите записать, с помощью таких методов, как putInt() и putString(). Затем вызовите apply() или commit(), чтобы сохранить изменения. Пример
Вывод: developer.android.com предлагает рассмотреть возможность перехода к хранилищу данных вместо SharedPreferences. Но, хотя Java не поддерживает хранилище данных, лучше использовать SharedPreferences. если ваше приложение использует Kotlin или RxJava — лучше использовать хранилище данных
Ответ №2:
13 января 2021 г.
Выпущена версия 1.0.0-alpha06. Добавлена поддержка RxJava 2/3, поэтому хранилище данных теперь можно использовать на Java.
Добавлены оболочки RxJava для хранилища данных. Артефакты хранилища данных-rxjava2 / 3 содержат оболочки для основных API-интерфейсов хранилища данных (RxDataStore, RxDataStoreBuilder и RxDataMigration). Артефакты datastore-preferences-rxjava2 / 3 содержат конструктор для создания хранилища данных настроек.
Для этого вы должны добавить зависимости:
// optional - RxJava2 support
implementation "androidx.datastore:datastore-rxjava2:1.0.0-alpha06"
// optional - RxJava3 support
implementation "androidx.datastore:datastore-rxjava3:1.0.0-alpha06"
Кроме того, теперь официальная документация хранилища данных содержит эквиваленты примеров кода для Java.
Комментарии:
1. Могу ли я использовать хранилище данных в обычной Java? Или только в RxJava-приложениях
2. @Виктор Поздняков, на данный момент из коробки у вас есть только два варианта — сопрограммы Kotlin и RxJava. Хотя библиотека все еще находится в альфа-версии, возможно, будут какие-то изменения (кто знает, может
ListenableFuture
быть, скоро будет добавлена поддержка Guava)3. ДА. В простых java-проектах нам остается использовать SharedPreferences. Надеюсь, в будущем хранилище данных можно будет использовать на обычной Java
Ответ №3:
Я уверен, что они не планируют делать это для Java.
Хранилище данных, построенное на сопрограммах Kotlin и Flow, предоставляет две разные реализации: хранилище данных Proto, которое позволяет хранить типизированные объекты (поддерживаемые буферами протокола) и хранилище данных Preferences, в котором хранятся пары ключ-значение. Данные хранятся асинхронно, последовательно и транзакционно, преодолевая большинство недостатков SharedPreferences.
Насколько я понимаю, сопрограммы / потоки Kotlin недоступны для java. Вы можете прочитать больше здесь, хорошая статья от Florina.
Ответ №4:
Я согласен с ответом @Victor Pozdnyakov. Итак, я не буду здесь повторять это, но я действительно изо всех сил пытался заставить это работать на java только для сохранения одного значения; Я не нашел никаких указаний на это, поэтому мне пришлось копаться в RxJava
документации.
Вот пример сохранения значения int и возврата его без непрерывного наблюдения за данными (точно так же, как вы делаете с SharedPreferences
)
Зависимости:
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"
Приведенный пример с описанием комментариев:
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);
}
}