具有共享偏好的 LiveData
LiveData with shared preferences
我有一个设置屏幕,我正在其中设置一些值。当我设置这些值时,它会保存在共享首选项中,并且我需要这些值
请求网络 api 作为参数调用。
现在我可以在我的 activity 中使用共享首选项的侦听器,然后进行 api 调用并获取新数据,但我想将其与 LiveData 一起使用。
如何使用 LiveData 监听共享首选项的变化,然后使用新参数进行网络调用。
我看到您的挑战是在 API 在 ViewModel 或 LiveData 中调用时调用共享首选项值。
您可以在应用程序 class 中将您的共享首选项定义为全局(因此它将是全局的)
public class MyApplication extends Application {
public static AppPreferences shared_preference;
/*On Create Application Create AppPreferences*/
@Override
public void onCreate() {
super.onCreate();
shared_preference = AppPreferences.getInstance(this);
}
}
并且您可以通过在 ViewModel 中调用共享首选项来更新或保存值
/*Save to Shared Preferences*/
MyApplication.shared_preference.setLogin(true);
希望这对你有帮助,因为我在那里看到了你的问题,这对我有用并且能够在 API 调用中插入参数。
假设您的网络请求已经为您提供了 LiveData class。例如 Retrofit and a CallAdapter like LiveDataCallAdapter.
一旦您通过以下任一方法获得了最后一个观测值:
- 为共享首选项应用侦听器
OnSharedPreferenceChangeListener
,正如您已经提到的,以更新 MutableLiveData
- 或者使用像 rharter/SharedPreferenceLiveData.kt
这样的 SharedPreferences LiveData
那么你可以将之前的LiveData应用于:
- A Transformations.switchMap as in UserViewModel.kt(下面引用的相关部分)
- 或作为 MediatorLiveData addSource 方法的参数。
这是 UserViewModel.kt 中 Transformations.switchMap 的相关示例:
private val _login = MutableLiveData<String>()
val login: LiveData<String>
get() = _login
val repositories: LiveData<Resource<List<Repo>>> = Transformations
.switchMap(_login) { login ->
if (login == null) {
AbsentLiveData.create()
} else {
repoRepository.loadRepos(login)
}
}
下面一段很棒的代码是 SharedPreference 的 LiveData 实现。它完美运行。
package com.chargingwatts.chargingalarm.util.preference;
import android.arch.lifecycle.LiveData
import android.content.SharedPreferences
abstract class SharedPreferenceLiveData<T>(val sharedPrefs: SharedPreferences,
val key: String,
val defValue: T) : LiveData<T>() {
private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
if (key == this.key) {
value = getValueFromPreferences(key, defValue)
}
}
abstract fun getValueFromPreferences(key: String, defValue: T): T
override fun onActive() {
super.onActive()
value = getValueFromPreferences(key, defValue)
sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
}
override fun onInactive() {
sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
super.onInactive()
}
}
class SharedPreferenceIntLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Int) :
SharedPreferenceLiveData<Int>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Int): Int = sharedPrefs.getInt(key, defValue)
}
class SharedPreferenceStringLiveData(sharedPrefs: SharedPreferences, key: String, defValue: String) :
SharedPreferenceLiveData<String>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: String): String = sharedPrefs.getString(key, defValue)
}
class SharedPreferenceBooleanLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Boolean) :
SharedPreferenceLiveData<Boolean>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Boolean): Boolean = sharedPrefs.getBoolean(key, defValue)
}
class SharedPreferenceFloatLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Float) :
SharedPreferenceLiveData<Float>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Float): Float = sharedPrefs.getFloat(key, defValue)
}
class SharedPreferenceLongLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Long) :
SharedPreferenceLiveData<Long>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Long): Long = sharedPrefs.getLong(key, defValue)
}
class SharedPreferenceStringSetLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Set<String>) :
SharedPreferenceLiveData<Set<String>>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Set<String>): Set<String> = sharedPrefs.getStringSet(key, defValue)
}
fun SharedPreferences.intLiveData(key: String, defValue: Int): SharedPreferenceLiveData<Int> {
return SharedPreferenceIntLiveData(this, key, defValue)
}
fun SharedPreferences.stringLiveData(key: String, defValue: String): SharedPreferenceLiveData<String> {
return SharedPreferenceStringLiveData(this, key, defValue)
}
fun SharedPreferences.booleanLiveData(key: String, defValue: Boolean): SharedPreferenceLiveData<Boolean> {
return SharedPreferenceBooleanLiveData(this, key, defValue)
}
fun SharedPreferences.floatLiveData(key: String, defValue: Float): SharedPreferenceLiveData<Float> {
return SharedPreferenceFloatLiveData(this, key, defValue)
}
fun SharedPreferences.longLiveData(key: String, defValue: Long): SharedPreferenceLiveData<Long> {
return SharedPreferenceLongLiveData(this, key, defValue)
}
fun SharedPreferences.stringSetLiveData(key: String, defValue: Set<String>): SharedPreferenceLiveData<Set<String>> {
return SharedPreferenceStringSetLiveData(this, key, defValue)
}
Java Code by Idish,虽然他在这里发表了评论,但不确定,为什么他没有将其添加为答案。
在下面粘贴相同的代码:
public abstract class SharedPreferenceLiveData<T> extends LiveData<T> {
SharedPreferences sharedPrefs;
String key;
public T defValue;
public SharedPreferenceLiveData(SharedPreferences prefs, String key, T defValue) {
this.sharedPrefs = prefs;
this.key = key;
this.defValue = defValue;
}
private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (SharedPreferenceLiveData.this.key.equals(key)) {
setValue(getValueFromPreferences(key, defValue));
}
}
};
abstract T getValueFromPreferences(String key, T defValue);
@Override
protected void onActive() {
super.onActive();
setValue(getValueFromPreferences(key, defValue));
sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}
@Override
protected void onInactive() {
sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
super.onInactive();
}
public SharedPreferenceLiveData<Boolean> getBooleanLiveData(String key, Boolean defaultValue) {
return new SharedPreferenceBooleanLiveData(sharedPrefs,key, defaultValue);
}
}
SharedPreferenceBooleanLiveDataclass
public class SharedPreferenceBooleanLiveData extends SharedPreferenceLiveData<Boolean>{
public SharedPreferenceBooleanLiveData(SharedPreferences prefs, String key, Boolean defValue) {
super(prefs, key, defValue);
}
@Override
Boolean getValueFromPreferences(String key, Boolean defValue) {
return sharedPrefs.getBoolean(key, defValue);
}
}
像link中提到的下面的代码一样调用它:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferenceStringLiveData sharedPreferenceStringLiveData = new SharedPreferenceStringLiveData(preferences, "cid", "");
sharedPreferenceStringLiveData.getStringLiveData("cid", "").observe(this, cid -> {
Toast.makeText(this, "Change in CID "+cid, Toast.LENGTH_SHORT).show();
});
同样,如果使用 Preference Helper class,可以按如下方式调用 class:
只是一个例子:
public class PreferenceManager {
private SharedPreferenceBooleanLiveData sharedPreferenceLiveData;
public SharedPreferenceBooleanLiveData getSharedPrefs(){
return sharedPreferenceLiveData;
}
public void setSharedPreferences(String key, boolean value) {
SharedPreferences userDetails = context.getSharedPreferences(APP_PREFERENCE,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = userDetails.edit();
editor.putBoolean(key, value);
editor.apply();
sharedPreferenceLiveData = new SharedPreferenceBooleanLiveData(userDetails,key,value);
}
}
并且在 activity class 中调用它如下:
创建对象:
SharedPreferenceBooleanLiveData sharedPreferenceLiveData;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
sharedPreferenceLiveData = preferenceManager.getSharedPrefs();
}
观察如下:
sharedPreferenceLiveData.getBooleanLiveData(PreferenceKey.KEY_LOCATION_PERMISSION,false).observe(this,check->{
if(check){
setPermissionGranted(check);
}
});
在build.gradle(:app)
中添加以下依赖
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6" // replace with updated version
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6"// replace with updated version
在您的偏好中添加以下代码class/utils
private var mPrefs: SharedPreferences =
mContext.getSharedPreferences(AppConstant.PREF_NAME, Context.MODE_PRIVATE)
private val _constSate = MutableStateFlow(mPrefs.getBoolean(IS_NOTIFY,false))
// function for set data to preference and add to Stateflow.
fun setData(isNotify: Boolean){
// mPrefs = instance of your preference
mPrefs.edit().putBoolean(IS_NOTIFY, isNotify).apply()
_constSate.value = isNotify
}
//function for get observer/flow/live boolean value
fun getNotifyFlow() : StateFlow<Boolean> = _constSate
//在其他 class 上获取你的 observer/flow/live 值,例如 MainActivity.class 等。
CoroutineScope(Dispatchers.Main).launch{
appPreferences.getNotifyFlow().collect{
if (it){
Log.d("jai","true")
}else{
Log.d("jai","false")
}
}
}
Android 最近发布 DataStore 即:
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.
所以这是细分:
在项目的build.gradle
中:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
dependencies {
...
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha04"
}
数据库 class 看起来像:
class SettingsSharedPreference private constructor(context: Context) {
private val dataStore = context.createDataStore(name = "settings")
companion object {
val SCREEN_ORIENTATION = preferencesKey<String>("screen_orientation")
@Volatile
private var instance: SettingsSharedPreference? = null
private val lock = Any()
operator fun invoke(context: Context) = instance ?: synchronized(lock) {
instance ?: SettingsSharedPreference(context).also { instance = it }
}
}
val screenOrientationFlow: Flow<String> = dataStore.data
.map { preferences ->
preferences[SCREEN_ORIENTATION] ?: "landscape"
}
//TODO: You should use enum for screenOrientation, this is just an example
suspend fun setScreenOrientation(screenOrientation: String) {
dataStore.edit { preferences ->
preferences[SCREEN_ORIENTATION] = screenOrientation
}
}
}
在Activity中:
val settingsSharedPreference by lazy {
SettingsSharedPreference.invoke(this)
}
...
settingsSharedPreference.setScreenOrientation("portrait")
...
settingsSharedPreference.screenOrientationFlow.asLiveData().observe(this) { screenOrientation ->
...
}
我创建了一个纯 kotlin 库来执行此操作 - https://github.com/Jintin/PreferencesExtension
我们需要做的就是:
val preferenceLiveData = preference.liveData<String>(MY_KEY)
preferenceLiveData.observe(this) {
// get update here
}
并确保 preferenceLiveData 可以在 ViewModel 中并让 Activity/Fragment 观察它。
在此处查看示例:
Activity,
ViewModel
您可以在单个 LiveData 中组织所有 SharedPreferences 值
public class SharedPreferencesLiveData extends LiveData<ObservableArrayMap<String, Object>> {
private final SharedPreferences mSharedPreference;
public SharedPreferencesLiveData(final SharedPreferences sharedPreferences) {
super(new ObservableArrayMap<String, Object>() {
@Nullable
@Override
public Object put(String key, Object value) {
final Object lastValue = super.get(key);
if (!Objects.equals(value, lastValue)) {
if (value instanceof Boolean) {
sharedPreferences.edit().putBoolean(key, (Boolean) value).apply();
} else if (value instanceof Float) {
sharedPreferences.edit().putFloat(key, (Float) value).apply();
} else if (value instanceof String) {
sharedPreferences.edit().putString(key, (String) value).apply();
} else if (value instanceof Integer) {
sharedPreferences.edit().putInt(key, (Integer) value).apply();
} else if (value instanceof Long) {
sharedPreferences.edit().putLong(key, (Long) value).apply();
} else if (value instanceof Set) {
sharedPreferences.edit().putStringSet(key, (Set<String>) value).apply();
} else if (value == null) {
sharedPreferences.edit().remove(key).apply();
} else {
throw new IllegalArgumentException("value=" + value + " data type not support");
}
return super.put(key, value);
} else
return lastValue;
}
});
mSharedPreference = sharedPreferences;
}
@Override
protected void onActive() {
super.onActive();
getValue().clear();
getValue().putAll((SimpleArrayMap<? extends String, ?>) new ArrayMap<String, Object>() {{
putAll(mSharedPreference.getAll());
}});
mSharedPreference.registerOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener);
}
@Override
protected void onInactive() {
super.onInactive();
mSharedPreference.unregisterOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener);
}
SharedPreferences.OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, String key) {
if (sharedPreferences.contains(key)) {
getValue().put(key, sharedPreferences.getAll().get(key));
} else {
getValue().remove(key);
}
}
};
}
然后在 ViewModel 中声明 SharedPreferences 的 LiveData
public static class ViewModel extends AndroidViewModel {
public final SharedPreferencesLiveData sharedPreferenceLiveData = new SharedPreferencesLiveData(getApplication().getSharedPreferences("XXX", 0));
public ViewModel(@NonNull Application application) {
super(application);
}
}
然后从 XML 布局
访问和更新(双向数据绑定)您的 SharedPreferences
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="viewModel"
type="com.xxx.sharedpreferencedatabindingtest.MainActivity.ViewModel" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked='@={((Boolean)viewModel.sharedPreferenceLiveData["XXXX"])}'
android:text="XXX" />
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked='@={((Boolean)viewModel.sharedPreferenceLiveData["XXXX"])}'
android:text="XXX" />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="1000"
android:min="0"
android:progress='@={(Integer)(viewModel.sharedPreferenceLiveData["YYYY"])}' />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="1000"
android:min="0"
android:progress='@={(Integer)(viewModel.sharedPreferenceLiveData["YYYY"])}' />
</LinearLayout>
</layout>
我有一个设置屏幕,我正在其中设置一些值。当我设置这些值时,它会保存在共享首选项中,并且我需要这些值 请求网络 api 作为参数调用。
现在我可以在我的 activity 中使用共享首选项的侦听器,然后进行 api 调用并获取新数据,但我想将其与 LiveData 一起使用。
如何使用 LiveData 监听共享首选项的变化,然后使用新参数进行网络调用。
我看到您的挑战是在 API 在 ViewModel 或 LiveData 中调用时调用共享首选项值。
您可以在应用程序 class 中将您的共享首选项定义为全局(因此它将是全局的)
public class MyApplication extends Application {
public static AppPreferences shared_preference;
/*On Create Application Create AppPreferences*/
@Override
public void onCreate() {
super.onCreate();
shared_preference = AppPreferences.getInstance(this);
}
}
并且您可以通过在 ViewModel 中调用共享首选项来更新或保存值
/*Save to Shared Preferences*/
MyApplication.shared_preference.setLogin(true);
希望这对你有帮助,因为我在那里看到了你的问题,这对我有用并且能够在 API 调用中插入参数。
假设您的网络请求已经为您提供了 LiveData class。例如 Retrofit and a CallAdapter like LiveDataCallAdapter.
一旦您通过以下任一方法获得了最后一个观测值:
- 为共享首选项应用侦听器
OnSharedPreferenceChangeListener
,正如您已经提到的,以更新 MutableLiveData - 或者使用像 rharter/SharedPreferenceLiveData.kt 这样的 SharedPreferences LiveData
那么你可以将之前的LiveData应用于:
- A Transformations.switchMap as in UserViewModel.kt(下面引用的相关部分)
- 或作为 MediatorLiveData addSource 方法的参数。
这是 UserViewModel.kt 中 Transformations.switchMap 的相关示例:
private val _login = MutableLiveData<String>()
val login: LiveData<String>
get() = _login
val repositories: LiveData<Resource<List<Repo>>> = Transformations
.switchMap(_login) { login ->
if (login == null) {
AbsentLiveData.create()
} else {
repoRepository.loadRepos(login)
}
}
下面一段很棒的代码是 SharedPreference 的 LiveData 实现。它完美运行。
package com.chargingwatts.chargingalarm.util.preference;
import android.arch.lifecycle.LiveData
import android.content.SharedPreferences
abstract class SharedPreferenceLiveData<T>(val sharedPrefs: SharedPreferences,
val key: String,
val defValue: T) : LiveData<T>() {
private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
if (key == this.key) {
value = getValueFromPreferences(key, defValue)
}
}
abstract fun getValueFromPreferences(key: String, defValue: T): T
override fun onActive() {
super.onActive()
value = getValueFromPreferences(key, defValue)
sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
}
override fun onInactive() {
sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
super.onInactive()
}
}
class SharedPreferenceIntLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Int) :
SharedPreferenceLiveData<Int>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Int): Int = sharedPrefs.getInt(key, defValue)
}
class SharedPreferenceStringLiveData(sharedPrefs: SharedPreferences, key: String, defValue: String) :
SharedPreferenceLiveData<String>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: String): String = sharedPrefs.getString(key, defValue)
}
class SharedPreferenceBooleanLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Boolean) :
SharedPreferenceLiveData<Boolean>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Boolean): Boolean = sharedPrefs.getBoolean(key, defValue)
}
class SharedPreferenceFloatLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Float) :
SharedPreferenceLiveData<Float>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Float): Float = sharedPrefs.getFloat(key, defValue)
}
class SharedPreferenceLongLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Long) :
SharedPreferenceLiveData<Long>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Long): Long = sharedPrefs.getLong(key, defValue)
}
class SharedPreferenceStringSetLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Set<String>) :
SharedPreferenceLiveData<Set<String>>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Set<String>): Set<String> = sharedPrefs.getStringSet(key, defValue)
}
fun SharedPreferences.intLiveData(key: String, defValue: Int): SharedPreferenceLiveData<Int> {
return SharedPreferenceIntLiveData(this, key, defValue)
}
fun SharedPreferences.stringLiveData(key: String, defValue: String): SharedPreferenceLiveData<String> {
return SharedPreferenceStringLiveData(this, key, defValue)
}
fun SharedPreferences.booleanLiveData(key: String, defValue: Boolean): SharedPreferenceLiveData<Boolean> {
return SharedPreferenceBooleanLiveData(this, key, defValue)
}
fun SharedPreferences.floatLiveData(key: String, defValue: Float): SharedPreferenceLiveData<Float> {
return SharedPreferenceFloatLiveData(this, key, defValue)
}
fun SharedPreferences.longLiveData(key: String, defValue: Long): SharedPreferenceLiveData<Long> {
return SharedPreferenceLongLiveData(this, key, defValue)
}
fun SharedPreferences.stringSetLiveData(key: String, defValue: Set<String>): SharedPreferenceLiveData<Set<String>> {
return SharedPreferenceStringSetLiveData(this, key, defValue)
}
Java Code by Idish,虽然他在这里发表了评论,但不确定,为什么他没有将其添加为答案。
在下面粘贴相同的代码:
public abstract class SharedPreferenceLiveData<T> extends LiveData<T> {
SharedPreferences sharedPrefs;
String key;
public T defValue;
public SharedPreferenceLiveData(SharedPreferences prefs, String key, T defValue) {
this.sharedPrefs = prefs;
this.key = key;
this.defValue = defValue;
}
private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (SharedPreferenceLiveData.this.key.equals(key)) {
setValue(getValueFromPreferences(key, defValue));
}
}
};
abstract T getValueFromPreferences(String key, T defValue);
@Override
protected void onActive() {
super.onActive();
setValue(getValueFromPreferences(key, defValue));
sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}
@Override
protected void onInactive() {
sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
super.onInactive();
}
public SharedPreferenceLiveData<Boolean> getBooleanLiveData(String key, Boolean defaultValue) {
return new SharedPreferenceBooleanLiveData(sharedPrefs,key, defaultValue);
}
}
SharedPreferenceBooleanLiveDataclass
public class SharedPreferenceBooleanLiveData extends SharedPreferenceLiveData<Boolean>{
public SharedPreferenceBooleanLiveData(SharedPreferences prefs, String key, Boolean defValue) {
super(prefs, key, defValue);
}
@Override
Boolean getValueFromPreferences(String key, Boolean defValue) {
return sharedPrefs.getBoolean(key, defValue);
}
}
像link中提到的下面的代码一样调用它:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferenceStringLiveData sharedPreferenceStringLiveData = new SharedPreferenceStringLiveData(preferences, "cid", "");
sharedPreferenceStringLiveData.getStringLiveData("cid", "").observe(this, cid -> {
Toast.makeText(this, "Change in CID "+cid, Toast.LENGTH_SHORT).show();
});
同样,如果使用 Preference Helper class,可以按如下方式调用 class: 只是一个例子:
public class PreferenceManager {
private SharedPreferenceBooleanLiveData sharedPreferenceLiveData;
public SharedPreferenceBooleanLiveData getSharedPrefs(){
return sharedPreferenceLiveData;
}
public void setSharedPreferences(String key, boolean value) {
SharedPreferences userDetails = context.getSharedPreferences(APP_PREFERENCE,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = userDetails.edit();
editor.putBoolean(key, value);
editor.apply();
sharedPreferenceLiveData = new SharedPreferenceBooleanLiveData(userDetails,key,value);
}
}
并且在 activity class 中调用它如下: 创建对象:
SharedPreferenceBooleanLiveData sharedPreferenceLiveData;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
sharedPreferenceLiveData = preferenceManager.getSharedPrefs();
}
观察如下:
sharedPreferenceLiveData.getBooleanLiveData(PreferenceKey.KEY_LOCATION_PERMISSION,false).observe(this,check->{
if(check){
setPermissionGranted(check);
}
});
在build.gradle(:app)
中添加以下依赖 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6" // replace with updated version
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6"// replace with updated version
在您的偏好中添加以下代码class/utils
private var mPrefs: SharedPreferences =
mContext.getSharedPreferences(AppConstant.PREF_NAME, Context.MODE_PRIVATE)
private val _constSate = MutableStateFlow(mPrefs.getBoolean(IS_NOTIFY,false))
// function for set data to preference and add to Stateflow.
fun setData(isNotify: Boolean){
// mPrefs = instance of your preference
mPrefs.edit().putBoolean(IS_NOTIFY, isNotify).apply()
_constSate.value = isNotify
}
//function for get observer/flow/live boolean value
fun getNotifyFlow() : StateFlow<Boolean> = _constSate
//在其他 class 上获取你的 observer/flow/live 值,例如 MainActivity.class 等。
CoroutineScope(Dispatchers.Main).launch{
appPreferences.getNotifyFlow().collect{
if (it){
Log.d("jai","true")
}else{
Log.d("jai","false")
}
}
}
Android 最近发布 DataStore 即:
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.
所以这是细分:
在项目的build.gradle
中:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
dependencies {
...
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha04"
}
数据库 class 看起来像:
class SettingsSharedPreference private constructor(context: Context) {
private val dataStore = context.createDataStore(name = "settings")
companion object {
val SCREEN_ORIENTATION = preferencesKey<String>("screen_orientation")
@Volatile
private var instance: SettingsSharedPreference? = null
private val lock = Any()
operator fun invoke(context: Context) = instance ?: synchronized(lock) {
instance ?: SettingsSharedPreference(context).also { instance = it }
}
}
val screenOrientationFlow: Flow<String> = dataStore.data
.map { preferences ->
preferences[SCREEN_ORIENTATION] ?: "landscape"
}
//TODO: You should use enum for screenOrientation, this is just an example
suspend fun setScreenOrientation(screenOrientation: String) {
dataStore.edit { preferences ->
preferences[SCREEN_ORIENTATION] = screenOrientation
}
}
}
在Activity中:
val settingsSharedPreference by lazy {
SettingsSharedPreference.invoke(this)
}
...
settingsSharedPreference.setScreenOrientation("portrait")
...
settingsSharedPreference.screenOrientationFlow.asLiveData().observe(this) { screenOrientation ->
...
}
我创建了一个纯 kotlin 库来执行此操作 - https://github.com/Jintin/PreferencesExtension
我们需要做的就是:
val preferenceLiveData = preference.liveData<String>(MY_KEY)
preferenceLiveData.observe(this) {
// get update here
}
并确保 preferenceLiveData 可以在 ViewModel 中并让 Activity/Fragment 观察它。 在此处查看示例: Activity, ViewModel
您可以在单个 LiveData 中组织所有 SharedPreferences 值
public class SharedPreferencesLiveData extends LiveData<ObservableArrayMap<String, Object>> {
private final SharedPreferences mSharedPreference;
public SharedPreferencesLiveData(final SharedPreferences sharedPreferences) {
super(new ObservableArrayMap<String, Object>() {
@Nullable
@Override
public Object put(String key, Object value) {
final Object lastValue = super.get(key);
if (!Objects.equals(value, lastValue)) {
if (value instanceof Boolean) {
sharedPreferences.edit().putBoolean(key, (Boolean) value).apply();
} else if (value instanceof Float) {
sharedPreferences.edit().putFloat(key, (Float) value).apply();
} else if (value instanceof String) {
sharedPreferences.edit().putString(key, (String) value).apply();
} else if (value instanceof Integer) {
sharedPreferences.edit().putInt(key, (Integer) value).apply();
} else if (value instanceof Long) {
sharedPreferences.edit().putLong(key, (Long) value).apply();
} else if (value instanceof Set) {
sharedPreferences.edit().putStringSet(key, (Set<String>) value).apply();
} else if (value == null) {
sharedPreferences.edit().remove(key).apply();
} else {
throw new IllegalArgumentException("value=" + value + " data type not support");
}
return super.put(key, value);
} else
return lastValue;
}
});
mSharedPreference = sharedPreferences;
}
@Override
protected void onActive() {
super.onActive();
getValue().clear();
getValue().putAll((SimpleArrayMap<? extends String, ?>) new ArrayMap<String, Object>() {{
putAll(mSharedPreference.getAll());
}});
mSharedPreference.registerOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener);
}
@Override
protected void onInactive() {
super.onInactive();
mSharedPreference.unregisterOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener);
}
SharedPreferences.OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, String key) {
if (sharedPreferences.contains(key)) {
getValue().put(key, sharedPreferences.getAll().get(key));
} else {
getValue().remove(key);
}
}
};
}
然后在 ViewModel 中声明 SharedPreferences 的 LiveData
public static class ViewModel extends AndroidViewModel {
public final SharedPreferencesLiveData sharedPreferenceLiveData = new SharedPreferencesLiveData(getApplication().getSharedPreferences("XXX", 0));
public ViewModel(@NonNull Application application) {
super(application);
}
}
然后从 XML 布局
访问和更新(双向数据绑定)您的 SharedPreferences<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="viewModel"
type="com.xxx.sharedpreferencedatabindingtest.MainActivity.ViewModel" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked='@={((Boolean)viewModel.sharedPreferenceLiveData["XXXX"])}'
android:text="XXX" />
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked='@={((Boolean)viewModel.sharedPreferenceLiveData["XXXX"])}'
android:text="XXX" />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="1000"
android:min="0"
android:progress='@={(Integer)(viewModel.sharedPreferenceLiveData["YYYY"])}' />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="1000"
android:min="0"
android:progress='@={(Integer)(viewModel.sharedPreferenceLiveData["YYYY"])}' />
</LinearLayout>
</layout>