新的 Jetpack Datastore 是否仅适用于 Kotlin?
Is new Jetpack Datastore only for Kotlin?
我已经阅读了 Jetpack 的新库(现在处于 alpha 阶段)- Jetpack Datastore。
从文档中可以清楚地看出它是一种 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
如果我没有遗漏任何你不能在 Java 中使用这个库的东西。我对吗?我个人使用 Kotlin,但对我来说,这是 AndroidX 库的一个特殊先例。
我很确定他们没有计划 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.
就我而言,java 无法使用 Kotlin coroutines/flow。
您可以阅读更多 here,一篇来自 Florina 的精彩文章。
2021 年 1 月 13 日
Version 1.0.0-alpha06 已发布。添加了对 RxJava 2/3 的支持,因此现在可以在 Java 中使用 Datastore。
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.
为此你应该添加依赖项:
// optional - RxJava2 support
implementation "androidx.datastore:datastore-rxjava2:1.0.0-alpha06"
// optional - RxJava3 support
implementation "androidx.datastore:datastore-rxjava3:1.0.0-alpha06"
此外,现在 Datastore's official documentation 包含 Java 的代码示例等价物。
您现在可以使用 DataStore only in RxJava. In plain java you can use only SharedPreferences。让我们比较一下 RxJava DataStore Preferences 和 SharedPreferences
1) 访问
数据存储:
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();
共享首选项:
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
2) 阅读:
数据存储:
为您的值定义一个键(例如 int 值),然后访问数据存储区的数据:PreferencesKeys.int("example_counter")
data()
- 访问DataStore的数据。这个属性returns一个Flow
map()
- returns a Flow 其中包含将给定函数应用于原始 Flow
的每个值的结果
SharedPreferences
sharedPref.getInt("highScoreKey", 0);
要从共享首选项文件中检索值,请使用默认值(此处为 o)提供您想要的值的键
3) 写入
数据存储:
以事务方式更新 DataStore 中的数据
共享首选项:
使用SharedPreferences.Editor 传递您要使用putInt() 和putString() 等方法编写的键和值。然后调用 apply() 或 commit() 来保存更改。 Example
结论: developer.android.com 建议考虑迁移到 DataStore 而不是 SharedPreferences。但是 Java 不支持 DataStore,最好使用 SharedPreferences。如果您的应用程序使用 Kotlin 或 RxJava - 最好使用 DataStore
我同意@Victor Pozdnyakov 的回答。所以,我不会在这里重申这一点,但我真的很难让它在 java 中工作,只是为了保存一个值;我没有找到任何 tuts,所以我不得不深入研究 RxJava
文档。
这是一个存储 int 值的示例,return 它没有连续的数据观察(就像你对 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);
}
}
我已经阅读了 Jetpack 的新库(现在处于 alpha 阶段)- Jetpack Datastore。
从文档中可以清楚地看出它是一种 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
如果我没有遗漏任何你不能在 Java 中使用这个库的东西。我对吗?我个人使用 Kotlin,但对我来说,这是 AndroidX 库的一个特殊先例。
我很确定他们没有计划 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.
就我而言,java 无法使用 Kotlin coroutines/flow。 您可以阅读更多 here,一篇来自 Florina 的精彩文章。
2021 年 1 月 13 日
Version 1.0.0-alpha06 已发布。添加了对 RxJava 2/3 的支持,因此现在可以在 Java 中使用 Datastore。
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.
为此你应该添加依赖项:
// optional - RxJava2 support
implementation "androidx.datastore:datastore-rxjava2:1.0.0-alpha06"
// optional - RxJava3 support
implementation "androidx.datastore:datastore-rxjava3:1.0.0-alpha06"
此外,现在 Datastore's official documentation 包含 Java 的代码示例等价物。
您现在可以使用 DataStore only in RxJava. In plain java you can use only SharedPreferences。让我们比较一下 RxJava DataStore Preferences 和 SharedPreferences
1) 访问
数据存储:
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();
共享首选项:
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
2) 阅读:
数据存储: 为您的值定义一个键(例如 int 值),然后访问数据存储区的数据:PreferencesKeys.int("example_counter")
data()
- 访问DataStore的数据。这个属性returns一个Flow
map()
- returns a Flow 其中包含将给定函数应用于原始 Flow
SharedPreferences
sharedPref.getInt("highScoreKey", 0);
要从共享首选项文件中检索值,请使用默认值(此处为 o)提供您想要的值的键
3) 写入
数据存储:
以事务方式更新 DataStore 中的数据
共享首选项:
使用SharedPreferences.Editor 传递您要使用putInt() 和putString() 等方法编写的键和值。然后调用 apply() 或 commit() 来保存更改。 Example
结论: developer.android.com 建议考虑迁移到 DataStore 而不是 SharedPreferences。但是 Java 不支持 DataStore,最好使用 SharedPreferences。如果您的应用程序使用 Kotlin 或 RxJava - 最好使用 DataStore
我同意@Victor Pozdnyakov 的回答。所以,我不会在这里重申这一点,但我真的很难让它在 java 中工作,只是为了保存一个值;我没有找到任何 tuts,所以我不得不深入研究 RxJava
文档。
这是一个存储 int 值的示例,return 它没有连续的数据观察(就像你对 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);
}
}