Skip to content Skip to sidebar Skip to footer

Livedata With Shared Preferences

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 ca

Solution 1:

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

abstractclassSharedPreferenceLiveData<T>(val sharedPrefs: SharedPreferences,
                                           val key: String,
                                           val defValue: T) : LiveData<T>() {

    privateval preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
        if (key == this.key) {
            value = getValueFromPreferences(key, defValue)
        }
    }

    abstractfungetValueFromPreferences(key: String, defValue: T): T

    overridefunonActive() {
        super.onActive()
        value = getValueFromPreferences(key, defValue)
        sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
    }

    overridefunonInactive() {
        sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
        super.onInactive()
    }
}

classSharedPreferenceIntLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Int) :
        SharedPreferenceLiveData<Int>(sharedPrefs, key, defValue) {
    overridefungetValueFromPreferences(key: String, defValue: Int): Int = sharedPrefs.getInt(key, defValue)
}

classSharedPreferenceStringLiveData(sharedPrefs: SharedPreferences, key: String, defValue: String) :
        SharedPreferenceLiveData<String>(sharedPrefs, key, defValue) {
    overridefungetValueFromPreferences(key: String, defValue: String): String = sharedPrefs.getString(key, defValue)
}

classSharedPreferenceBooleanLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Boolean) :
        SharedPreferenceLiveData<Boolean>(sharedPrefs, key, defValue) {
    overridefungetValueFromPreferences(key: String, defValue: Boolean): Boolean = sharedPrefs.getBoolean(key, defValue)
}

classSharedPreferenceFloatLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Float) :
        SharedPreferenceLiveData<Float>(sharedPrefs, key, defValue) {
    overridefungetValueFromPreferences(key: String, defValue: Float): Float = sharedPrefs.getFloat(key, defValue)
}

classSharedPreferenceLongLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Long) :
        SharedPreferenceLiveData<Long>(sharedPrefs, key, defValue) {
    overridefungetValueFromPreferences(key: String, defValue: Long): Long = sharedPrefs.getLong(key, defValue)
}

classSharedPreferenceStringSetLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Set<String>) :
        SharedPreferenceLiveData<Set<String>>(sharedPrefs, key, defValue) {
    overridefungetValueFromPreferences(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)
}

Solution 2:

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

Pasting the same code below:

publicabstractclassSharedPreferenceLiveData<T> extendsLiveData<T> {

SharedPreferences sharedPrefs;
String key;
public T defValue;

publicSharedPreferenceLiveData(SharedPreferences prefs, String key, T defValue) {
    this.sharedPrefs = prefs;
    this.key = key;
    this.defValue = defValue;
}

privateSharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener = newSharedPreferences.OnSharedPreferenceChangeListener() {
    @OverridepublicvoidonSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (SharedPreferenceLiveData.this.key.equals(key)) {
            setValue(getValueFromPreferences(key, defValue));
        }
    }
};
abstract T getValueFromPreferences(String key, T defValue);

@OverrideprotectedvoidonActive() {
    super.onActive();
    setValue(getValueFromPreferences(key, defValue));
    sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}

@OverrideprotectedvoidonInactive() {
    sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
    super.onInactive();
}
publicSharedPreferenceLiveData<Boolean> getBooleanLiveData(String key, Boolean defaultValue) {
    returnnewSharedPreferenceBooleanLiveData(sharedPrefs,key, defaultValue);
}
}

SharedPreferenceBooleanLiveData class

publicclassSharedPreferenceBooleanLiveDataextendsSharedPreferenceLiveData<Boolean>{

publicSharedPreferenceBooleanLiveData(SharedPreferences prefs, String key, Boolean defValue) {
    super(prefs, key, defValue);
}

@OverrideBooleangetValueFromPreferences(String key, Boolean defValue) {
    return sharedPrefs.getBoolean(key, defValue);
}

}

Calling this like the below code mentioned in this link:

SharedPreferencespreferences= PreferenceManager.getDefaultSharedPreferences(this);
 SharedPreferenceStringLiveDatasharedPreferenceStringLiveData=newSharedPreferenceStringLiveData(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:

publicclassPreferenceManager {
privateSharedPreferenceBooleanLiveData sharedPreferenceLiveData;

publicSharedPreferenceBooleanLiveDatagetSharedPrefs(){
        return sharedPreferenceLiveData;
    }

publicvoidsetSharedPreferences(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 = newSharedPreferenceBooleanLiveData(userDetails,key,value);
    }
}

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

SharedPreferenceBooleanLiveData sharedPreferenceLiveData;
@OverridepublicvoidonActivityCreated(@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);
        }
    });

Solution 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:

Then you can apply the previous LiveData to either:

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

Solution 4:

Android recently released DataStore which is:

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.

So here is the breakdown:

In the build.gradle of the project:

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

The database class would look like:

classSettingsSharedPreferenceprivateconstructor(context: Context) {

    privateval dataStore = context.createDataStore(name = "settings")

    companionobject {

        val SCREEN_ORIENTATION = preferencesKey<String>("screen_orientation")

        @Volatileprivatevar instance: SettingsSharedPreference? = nullprivateval lock = Any()

        operatorfuninvoke(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 examplesuspendfunsetScreenOrientation(screenOrientation: String) {
        dataStore.edit { preferences ->
            preferences[SCREEN_ORIENTATION] = screenOrientation
        }
    }
}

In the Activity:

val settingsSharedPreference by lazy {
    SettingsSharedPreference.invoke(this)
}
...
settingsSharedPreference.setScreenOrientation("portrait")    
...
settingsSharedPreference.screenOrientationFlow.asLiveData().observe(this) { screenOrientation ->
    ...
}

Solution 5:

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)

publicclassMyApplicationextendsApplication {
   publicstatic AppPreferences shared_preference;

   /*On Create Application Create AppPreferences*/@OverridepublicvoidonCreate() {
     super.onCreate();
     shared_preference = AppPreferences.getInstance(this);
   }
}

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

/*Save toShared 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.

Post a Comment for "Livedata With Shared Preferences"