NiceToMytyuk
NiceToMytyuk

Reputation: 4287

Summary doesn't persists on dynamically load data in ListPreference

In my SettingActivity I'm loading some data to be shown in ListPreference from Room, once the items are selected all works correctly, the value is saved to `SharedPreferences and the summary is shown correctly, but once I return to SettingsActivity the summary value is reset to null.

Here is what is happening:

enter image description here

My code is pretty simple, onViewCreated() I start observing LiveData to be shown in ListPreference and then I set the values for entries and entryValues

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel.shops.observe(viewLifecycleOwner) {
        setShopsPreferences(it)
    }
}

private fun setShopsPreferences(shops: List<Shop>) {
    val shopsPreference = preferenceManager.findPreference<ListPreference>("defaultShop")
    if (shops.isEmpty()) {
        shopsPreference?.isEnabled = false
        return
    } else {
        shopsPreference?.isEnabled = true
    }

    val entries: ArrayList<String> = ArrayList()
    val entryValues: ArrayList<String> = ArrayList()

    shops.forEach {
        entries.add(it.description)
        entryValues.add(it.id)
    }

    shopsPreference?.entryValues = entryValues.toArray(arrayOfNulls<CharSequence>(entryValues.size))
    shopsPreference?.entries = entries.toArray(arrayOfNulls<CharSequence>(entries.size))
}

ViewModel:

@HiltViewModel
class ShopsViewModel @Inject constructor(repository: ShopsRepository) : ViewModel() {
    private val _shops = MutableLiveData<List<Shop>>()
    val shops: LiveData<List<Shop>> = _shops

    init {
        repository.getAllShops().observeForever {
            _shops.value = it
        }
    }
}

Repository:

fun getAllShops(): LiveData<List<Shop>> {
    return shops.select()
}

DAO:

@Dao
interface ShopsDAO {
    @Query("SELECT * FROM shops")
    fun select(): LiveData<List<Shop>>
}

Upvotes: 1

Views: 106

Answers (2)

NiceToMytyuk
NiceToMytyuk

Reputation: 4287

To resolve the issue with dynamic data in a ListPreference I've made some changes to my code, first of call in onCreatePreferences() I've added a preference listener to my ListPreference like this:

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.root_preferences, rootKey)

        val shopsPreference = preferenceManager.findPreference<ListPreference>("defaultShop")

        shopsPreference?.setOnPreferenceChangeListener { preference, newValue ->
            val description = viewModel.shops.value?.find { it.id == newValue }
            preference.summary = description?.description
            true
        }
}

So in that way on each new selection, I'm looking for the matching value for that preference in my ViewModel and getting the description for it which then is set as the summary.

While to set the summary every time the list has been changed or the SettingsActivity is opened I've added the following code to my setShopsPreferences() function:

private fun setShopsPreferences(shops: List<Shop>?) {
    if (shops == null) {
        return
    }

    val shopsPreference = preferenceManager.findPreference<ListPreference>("defaultShop")
    // The preference is enabled only if there are shows inside the list
    shopsPreference?.isEnabled = shops.isNotEmpty()
    
    // Getting the defaultShop preference value, which will be used to find the actual shop description
    val defaultShop = sharedPreferences.getString("defaultShop", "0")
    defaultShop?.let { shopId ->
        // Setting the summary based on defaultShop saved preference
        shopsPreference?.summary = shops.find { it.id == shopId }?.description
    }

    val entries: ArrayList<String> = ArrayList()
    val entryValues: ArrayList<String> = ArrayList()

    shops.forEach {
        entries.add(it.description)
        entryValues.add(it.id)
    }

    shopsPreference?.entryValues =
        entryValues.toArray(arrayOfNulls<CharSequence>(entryValues.size))
    shopsPreference?.entries = entries.toArray(arrayOfNulls<CharSequence>(entries.size))
}

Upvotes: 0

Ananta Raha
Ananta Raha

Reputation: 1071

You are populating list entries dynamically after the preference hierarchy is already created by inflating the xml. But during that time there was no entry, hence the value was null. The data was then retrieved asynchronously but the change will not be reflected. So you have to set the summary manually.

Another approach I'm not sure about is to call recreate on the activity after populating the data inside the observer listener.

Upvotes: 1

Related Questions