Why updating PreferenceManager doesn#39;t trigger recomposition in Jetpack Compose?(为什么更新PferenceManager不会在Jetpack Compose中触发重新合成?)
问题描述
我正在学习article作曲。
无状态Composable是指不包含任何状态的Composable。实现无状态的一个简单方法是使用状态提升,所以我将代码B替换为代码A,这很棒!
文章告诉我:
通过将状态从HelloContent中提升出来,可以更容易地对可组合元素进行推理、在不同情况下重用它以及进行测试。HelloContent与其状态的存储方式分离。分离意味着,如果您修改或替换HelloScreen,则不必更改HelloContent的实现方式。
所以我写了代码C,它把name
的值存储在SharedPreferences
中,我觉得代码C就像代码A一样,但实际上代码C不能输入任何字母,代码C有什么问题?
代码A
@Composable
fun HelloScreen() {
var name by rememberSaveable { mutableStateOf("") }
HelloContent(name = name, onNameChange = { name = it })
}
@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Hello, $name",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.h5
)
OutlinedTextField(
value = name,
onValueChange = onNameChange,
label = { Text("Name") }
)
}
}
代码B
@Composable
fun HelloContent() {
Column(modifier = Modifier.padding(16.dp)) {
var name by remember { mutableStateOf("") }
if (name.isNotEmpty()) {
Text(
text = "Hello, $name!",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.h5
)
}
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text("Name") }
)
}
}
代码C
@Composable
fun HelloScreen() {
var name: String by PreferenceTool( LocalContext.current ,"zipCode", "World")
HelloContent(name = name, onNameChange = { name = it })
}
@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Hello, $name",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.h5
)
OutlinedTextField(
value = name,
onValueChange = onNameChange,
label = { Text("Name") }
)
}
}
class PreferenceTool<T>(
private val context: Context,
private val name: String,
private val default: T
) {
private val prefs: SharedPreferences by lazy {
PreferenceManager.getDefaultSharedPreferences(context)
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = findPreference(name, default)
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
putPreference(name, value)
}
@Suppress("UNCHECKED_CAST")
private fun findPreference(name: String, default: T): T = with(prefs) {
val res: Any = when (default) {
is Long -> getLong(name, default)
is String -> getString(name, default) ?: default
is Int -> getInt(name, default)
is Boolean -> getBoolean(name, default)
is Float -> getFloat(name, default)
else -> throw IllegalArgumentException("This type can be saved into Preferences")
}
res as T
}
@SuppressLint("CommitPrefEdits")
private fun putPreference(name: String, value: T) = with(prefs.edit()) {
when (value) {
is Long -> putLong(name, value)
is String -> putString(name, value)
is Int -> putInt(name, value)
is Boolean -> putBoolean(name, value)
is Float -> putFloat(name, value)
else -> throw IllegalArgumentException("This type can't be saved into Preferences")
}.apply()
}
}
推荐答案
Om关于代码无法工作的原因是完全正确的,他的答案将会工作。
为了了解写作中为什么需要MutableState
,我建议您从documentation开始,包括说明基本原则的this youtube video。
但PreferenceManager
已弃用,现在您可以改用DataStore
。
with Compose in可以这样使用:
@Composable
fun <T> rememberPreference(
key: Preferences.Key<T>,
defaultValue: T,
): MutableState<T> {
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current
val state = remember {
context.dataStore.data
.map {
it[key] ?: defaultValue
}
}.collectAsState(initial = defaultValue)
return remember {
object : MutableState<T> {
override var value: T
get() = state.value
set(value) {
coroutineScope.launch {
context.dataStore.edit {
it[key] = value
}
}
}
override fun component1() = value
override fun component2(): (T) -> Unit = { value = it }
}
}
}
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "preferences")
用法:
var name by rememberPreference(stringPreferencesKey("zipCode"), "World")
这篇关于为什么更新PferenceManager不会在Jetpack Compose中触发重新合成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么更新PferenceManager不会在Jetpack Compose中触发重新合成?


- Android viewpager检测滑动超出范围 2022-01-01
- 使用自定义动画时在 iOS9 上忽略 edgesForExtendedLayout 2022-01-01
- MalformedJsonException:在第1行第1列路径中使用JsonReader.setLenient(True)接受格式错误的JSON 2022-01-01
- 如何检查发送到 Android 应用程序的 Firebase 消息的传递状态? 2022-01-01
- 用 Swift 实现 UITextFieldDelegate 2022-01-01
- 在测试浓缩咖啡时,Android设备不会在屏幕上启动活动 2022-01-01
- Android - 拆分 Drawable 2022-01-01
- Android - 我如何找出用户有多少未读电子邮件? 2022-01-01
- android 4中的android RadioButton问题 2022-01-01
- 想使用ViewPager,无法识别android.support.*? 2022-01-01