помнить производноеStateOf или нет
В примерах, которые я нахожу (здесь или здесь), я вижу, что всегда завернуто в блок. Проверяя количество рекомпозиций, я не вижу разницы между
val foo = remember { derivedStateOf { someState } }
и
val foo = derivedStateOf { someState }
Может ли кто-нибудь показать мне пример, где результат будет отличаться?
Изменить: Итак, в этом примере я получил другой результат:
@Composable
fun Test() {
var count by remember {
mutableStateOf(0)
}
val moreThanOne = derivedStateOf {
Log.d("foo", "Calculate")
count > 1
}
Log.d("foo", "Read")
moreThanOne.value
Button(
onClick = {
Log.d("foo", "Clicked")
count += 1
}
) {
Text(text = "Increment")
}
}
Двойное нажатие на кнопку приводит к следующему журналу:
Read
Calculate
Clicked
Calculate
Clicked
Calculate
Read
Calculate
ОбертываниеderivedStateOf
сremember
однако журналы:
Read
Calculate
Clicked
Calculate
Clicked
Calculate
Read
Все еще не совсем уверен, почему я вижу то, что вижу.
1 ответ
Ваш код должен выглядеть так:
@Composable
fun Test() {
var count by remember {
mutableStateOf(0)
}
val moreThanOne = remember {
derivedStateOf {
Log.d("foo", "Calculate")
count > 1
}
}
Log.d("foo", "Read")
moreThanOne.value
Button(
onClick = {
Log.d("foo", "Clicked")
count += 1
}
) {
Text(text = "Increment")
}
}
Обратите внимание на дополнительные вокруг . Это не влияет на результаты регистрации, но отсутствиеremember
Во всем этом требуются дополнительные накладные расходы за счет создания нового каждый раз при запуске. Вы всегда должны помнитьderivedStateOf
когда в компонуемой функции.
Из этого кода я получаю следующее:
D/foo: Read
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
D/foo: Read
D/foo: Clicked
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
Первые и берутся из первоначального состава. Значение0
.
После первого щелчка издается, но больше ничего. Это вызвано тем, что становится условно недействительным при изменении . Это условно в том смысле, что вызывается только в том случае, если вычисленное значение отличается от предыдущего, прочитанного с помощью . В этом случае возвращаетсяfalse
опять так не называется.
Второй щелчокCalculate
снова виден и теперь производитtrue
что приводит к тому, что условная недействительность рассматривается как настоящая недействительность, и вызывается для обновления композиции.
Третий и последующие клики производятся только при вызове лямбды (потому чтоcount
изменено), но результат не отличается, поэтому условная недействительность игнорируется.
ПричинаCalculated
появляется раньше, хотя журналRead
находится перед выражением, что текущее значение обновляется перед вызовом, чтобы увидеть, нужно ли его вообще вызывать. Если, однако, был признан недействительным по какой-либо другой причине (то есть он прочитал какой-то другой объект состояния, который изменился), тоmoreThanOne
будет обновляться только вызовомmoreThanOne.value
. Объекты производного состояния обновляются перед вызовом только в том случае, если они являются единственной причинойTest
запрашивается повторный вызов. Если они возвращают то же значение, что и предыдущая композиция, то аннулирование игнорируется и вызов пропускается.