помнить производное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запрашивается повторный вызов. Если они возвращают то же значение, что и предыдущая композиция, то аннулирование игнорируется и вызов пропускается.

Другие вопросы по тегам