LiveData with shared preferences

左心房为你撑大大i 提交于 2019-12-05 16:55:16

问题


I have a settings screen where I am setting some values. When I set those values it gets saved in shared preferences and these values are needed in my request to the network api call as parameters.

Now I can use a listener for shared preferences in my activity then make an api call and get fresh data, but I want to use this with LiveData.

How can I listen for changes in the shared preferences using LiveData and then make the network call using the new parameters.


回答1:


Java Code by Idish, though he commented here, but not sure, why he didn't add it as answer.

Pasting the same code below:

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 class

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);
}

}

Calling this like the below code mentioned in this 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();
 });

Again if using a Preference Helper class, the class can be called as below: Just a sample:

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);
    }
}

And in the activity class call it as below: Create an object:

SharedPreferenceBooleanLiveData sharedPreferenceLiveData;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    sharedPreferenceLiveData = preferenceManager.getSharedPrefs();
}

And observe it as follows:

sharedPreferenceLiveData.getBooleanLiveData(PreferenceKey.KEY_LOCATION_PERMISSION,false).observe(this,check->{
        if(check){
            setPermissionGranted(check);
        }
    });



回答2:


The following awesome piece of code is LiveData Implementation of SharedPreference. It works perfectly.

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)
}



回答3:


Assuming your network request is already providing you a LiveData class. For example with Retrofit and a CallAdapter like LiveDataCallAdapter.

Once you have the last observed value by either:

  • Applying a listener for shared preferences OnSharedPreferenceChangeListener, as you already mentioned, to update a MutableLiveData
  • Or using a SharedPreferences LiveData like rharter/SharedPreferenceLiveData.kt

Then you can apply the previous LiveData to either:

  • A Transformations.switchMap as in UserViewModel.kt (related part quoted below)
  • Or as parameter for MediatorLiveData addSource method.

This is the related example for the Transformations.switchMap in UserViewModel.kt:

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)
        }
    }



回答4:


i see your challenge is calling Shared Preferences Value when API Calling in ViewModel or LiveData.

You may define your shared preference as global in Application class ( so it will be global)

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);
   }
}

And you may update or save value by calling Shared Preference in your ViewModel

/*Save to Shared Preferences*/
MyApplication.shared_preference.setLogin(true);

Wish this help you, cause i see your problem there, This is works for me and able to insert param in API Call.



来源:https://stackoverflow.com/questions/50649014/livedata-with-shared-preferences

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!