使用一个条目存储在Room表中的设置会在任何参数更新时触发所有观察者
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用一个条目存储在Room表中的设置会在任何参数更新时触发所有观察者相关的知识,希望对你有一定的参考价值。
我正在使用简单的Room表进行设置
@Entity
data class Settings(var user: String = "") {
@PrimaryKey
var id: Long = 1
var activeItem: Int = 0
var developerMode: Boolean = false
var logoUrl: String = ""
var advertisment: String = ""
}
我用LiveData观察表中的变化。问题是如果所有数据都在id为1的一个条目中,那么当表中的任何值更新时,所有观察者都会被触发。有没有办法如何强制LiveData仅在参数更改时观察,而不是整个条目?我不想通过附加表解决它或将其存储在具有不同ID的条目中
以下是Dao的询问:
@Query("SELECT activeItem FROM Settings WHERE id = 1")
abstract fun getActiveItem(): LiveData<Int>
@Query("SELECT user FROM Settings WHERE id = 1")
abstract fun getUser(): LiveData<String>
@Query("SELECT developerMode FROM Settings WHERE id = 1")
abstract fun getDeveloperMode(): LiveData<Boolean>
@Query("SELECT logoUrl FROM Settings WHERE id = 1")
abstract fun getLogoUrl(): LiveData<String>
@Query("SELECT advertisment FROM Settings WHERE id = 1")
abstract fun getAdvertisment(): LiveData<String>
答案
您应该使用SharedPreferences
来保持用户首选项。您可以通过首选项更改侦听器侦听首选项更新
preferences.registerOnSharedPreferenceChangeListener { sharedPreferences, key ->
// handle preference update
}
或者您可以实现自己的首选项注册表。
- 将您的偏好模型定义为
sealed class
sealed class MyPreference data class ActiveItemPreference(val number: Int) : MyPreference() data class UserPreference(val name: String, val age: Int) : MyPreference()
- 将
PreferenceRegistry
实现为类型安全的异构容器(Effective Java(3rd)。Item 33)object PreferencesRegistry { private val preferenceLiveDataMap: Map<KClass<*>, MutableLiveData<MyPreference>> = HashMap<KClass<*>, MutableLiveData<MyPreference>>().apply { addPreferenceLiveData(ActiveItemPreference::class) addPreferenceLiveData(UserPreference::class) /* Or you if you use kotlin-reflect you can register your preferences like this Preference::class.sealedSubclasses.forEach { preferenceClass -> addPreferenceLiveData(preferenceClass) } */ } operator fun <T : MyPreference> get(preferenceType: KClass<T>): LiveData<T> { @Suppress("UNCHECKED_CAST") val liveData = preferenceLiveDataMap[preferenceType] as? LiveData<T> return liveData ?: throw AssertionError("Unexpected preference type $preferenceType") } /** * Store receiver [T] of [toPreferences] extension to receiver [SharedPreferences] of [action] */ fun <T : MyPreference> T.toPreferences(context: Context, action: SharedPreferences.(T) -> Unit) { // get shared preferences to store T context.getSharedPreferences("preferences", Context.MODE_PRIVATE).action(this) // send new value of preference T to observers preferenceLiveDataMap[this::class]?.postValue(this) ?: AssertionError( "Unable to update preference live data of type ${this::class}") } /** * Helper extension for type safety */ private fun <T : MyPreference> MutableMap<KClass<*>, MutableLiveData<MyPreference>>.addPreferenceLiveData(type: KClass<T>) { put(type, MutableLiveData()) } }
看看以DSL方式实现的toPreferences
扩展,你可以在Kotlin in Action书(第11.2.1项)或Type-Safe Builders文章中阅读更多关于这种方法的内容。 - 现在您可以保存您的属性
UserPreference("Tom", 12).toPreferences(context) { (name, age) -> // extension for SharedPreferences from android SDK edit { putString("USER_NAME", name) putInt("USER_AGE", age) } }
- 并观察变化
PreferencesRegistry[UserPreference::class].observe(this::getLifecycle) { userPref -> if (userPref == null) Log.w("PREFERENCES", "Unexpected nullable user preference") else Log.d("PREFERENCES", "User preference updated. New name is ${userPref.name} and new age is ${userPref.age}") }
- 实现首选项加载并在应用程序启动时调用它
以上是关于使用一个条目存储在Room表中的设置会在任何参数更新时触发所有观察者的主要内容,如果未能解决你的问题,请参考以下文章