我有一个设置屏幕,我在其中设置一些值。当我设置这些值时,它会保存在共享首选项中,并且我需要这些值 请求将网络api调用作为参数。
现在我可以在我的活动中使用侦听器来获取共享首选项,然后进行api调用并获取新数据,但我想将它与LiveData一起使用。
如何使用LiveData侦听共享偏好设置中的更改,然后使用新参数进行网络呼叫。
答案 0 :(得分:5)
以下很棒的代码是SharedPreference的LiveData实现。效果很好。
signal_to_noise_ratio = 10
t=seq(0.1,10,0.1)
df <- data.frame(truesignal = sin(t))
df2 <- df
for (i in seq(5)) {
noise = rnorm(t)
k <- sqrt(var(t)/(signal_to_noise_ratio*var(noise)))
data_wNoise = t + k*noise
df2[,i] = sin(data_wNoise)
}
df[,2:6] = df2
df[,2:7] = rowSums(df2)
colnames(df) <- c("truesignal", "noisy1", "noisy2", "noisy3", "noisy4", "noisy5",
"stacked")
melt_df <- melt(df,measure.vars = 1:7, variable.name=c("signal"))
ggplot(data=melt_df,
aes(x=t,y=value,colour=factor(signal))) +
geom_path() +
facet_grid(signal~.)
答案 1 :(得分:1)
假设您的网络请求已经为您提供了LiveData类。例如,使用Retrofit和类似LiveDataCallAdapter的CallAdapter。
一旦您获得以下任一者的最后观测值:
undefined
应用侦听器以更新MutableLiveData 然后,您可以将以前的LiveData应用于以下任一情况:
这是UserViewModel.kt中Transformations.switchMap的相关示例:
OnSharedPreferenceChangeListener
答案 2 :(得分:1)
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);
}
}
SharedPreferenceBooleanLiveData类
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类,可以按以下方式调用该类: 只是一个示例:
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);
}
}
在活动类中按如下所示调用它: 创建一个对象:
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);
}
});
答案 3 :(得分:0)
我发现您的挑战是在ViewModel或LiveData中进行API调用时调用共享首选项值。
您可以在Application类中将共享首选项定义为全局(因此它将是全局的)
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调用中插入参数。
答案 4 :(得分:0)
在 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
///获得其他类(例如 MainActivity.class等)上的观察者/流量/实时值。
CoroutineScope(Dispatchers.Main).launch{
appPreferences.getNotifyFlow().collect{
if (it){
Log.d("jai","true")
}else{
Log.d("jai","false")
}
}
}
答案 5 :(得分:0)
Android最近发布了DataStore,即:
Jetpack DataStore是一种数据存储解决方案,可让您使用协议缓冲区存储键值对或类型化对象。 DataStore使用Kotlin协程和Flow异步,一致和事务地存储数据。
如果您当前正在使用SharedPreferences存储数据,请考虑迁移到DataStore。
这是细分:
在项目的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 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
}
}
}
在活动中:
val settingsSharedPreference by lazy {
SettingsSharedPreference.invoke(this)
}
...
settingsSharedPreference.setScreenOrientation("portrait")
...
settingsSharedPreference.screenOrientationFlow.asLiveData().observe(this) { screenOrientation ->
...
}
答案 6 :(得分:0)
我已经创建了一个纯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
答案 7 :(得分:0)
您可以在单个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>