英文:
Is new Jetpack Datastore only for Kotlin?
问题
我已阅读关于Jetpack的新库(现在处于alpha版本) - Jetpack Datastore。
从文档中可以清楚地看出,这是一种类似于Shared Preferences的替代方案
。
Jetpack DataStore是一种数据存储解决方案,允许您存储键值对或带有协议缓冲区的类型化对象。
DataStore使用Kotlin协程和Flow以异步、一致和事务方式存储数据。
如果您目前正在使用SharedPreferences存储数据,请考虑迁移到DataStore。
如果我没有漏掉什么,您不能在Java中使用这个库。我是对的吗?就我个人而言,我使用Kotlin,但对我来说,这是一个AndroidX库的特殊先例。
英文:
I've read about new library from Jetpack (now in alpha) - Jetpack Datastore.
It's clear from documentation that it's a sort of Shared Preferences' killer
> Jetpack DataStore is a data storage solution that allows you to store
> key-value pairs or typed objects with protocol buffers
>
> DataStore uses Kotlin coroutines and Flow to store data
> asynchronously, consistently, and transactionally
>
> If you're currently using SharedPreferences to store data, consider
> migrating to DataStore instead
If I don't miss anything you couldn't use this library in Java. Am I right? Personally I use Kotlin, but as for me it's a peculiar precedent for AndroidX library.
答案1
得分: 4
以下是您要翻译的内容:
可以仅在 RxJava 中使用 DataStore。在纯 Java 中,您现在只能使用 SharedPreferences。让我们比较 RxJava 中的 DataStore 首选项和 SharedPreferences。
1) 访问
DataStore:
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();
SharedPreferences:
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
2) 读取:
DataStore:
为您的值(例如整数值)定义一个键,然后访问数据存储的数据:PreferencesKeys.int("example_counter")
data()
- 访问 DataStore 的数据。此属性返回一个 Flow
map()
- 返回一个包含将给定函数应用于原始 Flow 的每个值的结果的 Flow
SharedPreferences
sharedPref.getInt("highScoreKey", 0);
要从共享首选项文件检索值,请提供您想要的值的键和默认值(例如此处为示例中的 "o")
3) 写入
DataStore:
以事务方式更新 DataStore 中的数据
SharedPreferences:
使用 SharedPreferences.Editor 传递要写入的键和值,使用诸如 putInt() 和 putString() 等方法。然后调用 apply() 或 commit() 以保存更改。示例
结论: developer.android.com 建议考虑迁移到 DataStore,而不是 SharedPreferences。但在 Java 不支持 DataStore 的情况下,最好使用 SharedPreferences。如果您的应用程序使用 Kotlin 或 RxJava - 最好使用 DataStore。
英文:
You can use DataStore only in RxJava. In plain java you can use only SharedPreferences now. Let's compare RxJava DataStore Preferences with SharedPreferences
1) access
DataStore:
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();
SharedPreferences:
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
2) read:
DataStore:
define a key for your value (in example for int value) and then access data of datastore : PreferencesKeys.int("example_counter")
data()
- access the data of DataStore. This property returns a Flow
map()
- returns a Flow which contains the results of applying the given function to each value of the original Flow
SharedPreferences
sharedPref.getInt("highScoreKey", 0);
To retrieve values from a shared preferences file provide the key for the value you want with default value (o here in example)
3) write
DataStore:
transactionally update data in a DataStore
SharedPreferences:
Using SharedPreferences.Editor pass the keys and values you want to write with methods such as putInt() and putString(). Then call apply() or commit() to save the changes. Example
Conclusion: developer.android.com suggests consider migrating to DataStore instead of SharedPreferences. But while Java doesn't support DataStore, it's better to use SharedPreferences. if your application uses Kotlin or RxJava - it's better to use DataStore
答案2
得分: 3
2021年1月13日
发布了版本1.0.0-alpha06。添加了对RxJava 2/3的支持,因此现在可以在Java中使用Datastore。
> 添加了DataStore的RxJava封装。datastore-rxjava2/3构件包含了核心DataStore API的封装(RxDataStore、RxDataStoreBuilder和RxDataMigration)。datastore-preferences-rxjava2/3构件包含了构建Preferences DataStore的构建器。
要实现这一点,您需要添加依赖项:
// 可选 - RxJava2支持
implementation "androidx.datastore:datastore-rxjava2:1.0.0-alpha06"
// 可选 - RxJava3支持
implementation "androidx.datastore:datastore-rxjava3:1.0.0-alpha06"
此外,现在Datastore的官方文档中包含了Java代码示例的等效内容。
英文:
January 13, 2021
Version 1.0.0-alpha06 was released. Support for RxJava 2/3 was added, so Datastore can be used in Java now.
> Added RxJava wrappers for DataStore. The datastore-rxjava2/3 artifacts
> contain the wrappers for the core DataStore APIs (RxDataStore,
> RxDataStoreBuilder, and RxDataMigration). The
> datastore-preferences-rxjava2/3 artifacts contain a builder to
> construct a Preferences DataStore.
For that you should add dependencies:
// optional - RxJava2 support
implementation "androidx.datastore:datastore-rxjava2:1.0.0-alpha06"
// optional - RxJava3 support
implementation "androidx.datastore:datastore-rxjava3:1.0.0-alpha06"
In addition now Datastore's official documentation holds code's examples' equivalents for Java.
答案3
得分: 1
我很确定他们没有计划为Java执行此操作。
基于Kotlin协程和Flow,DataStore提供了两种不同的实现方式:Proto DataStore,可以存储类型化对象(由协议缓冲支持),和Preferences DataStore,用于存储键值对。数据以异步、一致和事务性的方式存储,克服了大多数SharedPreferences的缺点。
据我所知,Kotlin协程/Flow在Java中不可用。
您可以在此处阅读更多信息,这是来自Florina的一篇很好的文章。
英文:
I pretty sure they do not hava plan to do it for java.
> Built on Kotlin coroutines and Flow, DataStore provides two different implementations: Proto DataStore, that lets you store typed objects (backed by protocol buffers) and Preferences DataStore, that stores key-value pairs. Data is stored asynchronously, consistently, and transactionally, overcoming most of the drawbacks of SharedPreferences.
Kotlin coroutines/flow are not available to java as far as I am concern.
You can read more here, a nice article from Florina.
答案4
得分: 1
以下是翻译好的内容:
我同意 @Victor Pozdnyakov 的答案。因此,我不会在这里重复那个,但是我在尝试在 Java 中使其工作时确实遇到了困难,只是为了保存一个单一的值;我没有找到任何关于这方面的教程,所以我不得不深入研究 RxJava
文档。
这里有一个示例,用于存储一个 int 值并在没有连续数据观察的情况下返回它(就像使用 SharedPreferences
一样)。
依赖项:
implementation "androidx.datastore:datastore-preferences:1.0.0"
// RxJava3 支持
implementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
带有说明性注释的示例:
public class MainActivity extends AppCompatActivity {
// 数据存储对象
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(this, "settings").build();
// 用于保存整数值的键
Preferences.Key<Integer> SOME_KEY = PreferencesKeys.intKey("SOME_KEY");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 将整数值存储到 DataStore,使用 SOME_KEY 键
saveInt(SOME_KEY, 1050);
// 立即读取数据,因为它已经被观察
observeInt(SOME_KEY, value -> runOnUiThread(() ->
Toast.makeText(this, "观察到的值:" + value, Toast.LENGTH_SHORT).show()));
// 在读取数据之前等待一些时间,因为需要一些时间才能存储;
// 因此不要在这里调用它,而是在其他某个事件上调用
readInt(SOME_KEY, value -> runOnUiThread(() ->
Toast.makeText(this, "值:" + value, Toast.LENGTH_SHORT).show()));
}
/**
* 将整数值保存到 DataStore,使用某个键
*
* @param key: 与要存储的值关联的键
* @param value: 要存储的值
*/
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();
}
/**
* 从 DataStore 返回与某个键关联的整数值,
* 一旦返回结果,订阅就会被处理掉。
*
* @param key: 与要存储的值关联的键
* @param listener: 该值在工作线程中返回,并使用监听器模式返回给调用者
*/
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();
}
/**
* 订阅一个观察者到与某个键关联的整数值,
* 订阅会将任何对该值的更改提交
*
* @param key: 与要存储的值关联的键
* @param listener: 该值在工作线程中返回,并使用监听器模式返回给调用者
*/
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 需要 `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);
}
}
英文:
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论