获取 Composable 中状态的先前值 - Jetpack Compose

cuo*_*gtd 3 android android-jetpack android-jetpack-compose

假设我的代码如下所示

@Composable
fun ExampleList() {
    val tickers by exampleViewModel.tickers.observeAsState()
    LazyColumn() {
        items(items = tickers) { ticker ->
            ExampleItem(ticker)
        }
    }
}
@Composable
fun ExampleItem(ticker: Ticker) {
    Text(text= ticker.lastPrice)
}
Run Code Online (Sandbox Code Playgroud)

每次更新股票代码时,是否都可以在ExampleItem Compose 中获取股票代码的先前值?
我想知道 React Native 中是否有类似 componentDidUpdate 的东西

and*_*ras 7

虽然答案在技术上是正确的,但第一个示例渲染了太多次,不幸的是我不理解第二个示例。

所以我回去看看它是如何完成的,这里React解释得很好:

这就是钩子(remember如你所愿)的样子(对于好奇的人来说):

function usePrevious<T>(value: T): T {
  // The ref object is a generic container whose current property is mutable ...
  // ... and can hold any value, similar to an instance property on a class
  const ref: any = useRef<T>();
  // Store current value in ref
  useEffect(() => {
    ref.current = value;
  }, [value]); // Only re-run if value changes
  // Return previous value (happens before update in useEffect above)
  return ref.current;
}
Run Code Online (Sandbox Code Playgroud)

可以以可重用的方式在 compose 中实现相同的想法(重要的是,@Composable在设置先前的值时不应重新渲染):

/**
 * Returns a dummy MutableState that does not cause render when setting it
 */
@Composable
fun <T> rememberRef(): MutableState<T?> {
    // for some reason it always recreated the value with vararg keys,
    // leaving out the keys as a parameter for remember for now
    return remember() {
        object: MutableState<T?> {
            override var value: T? = null

            override fun component1(): T? = value

            override fun component2(): (T?) -> Unit = { value = it }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和实际的rememberPrevious

function usePrevious<T>(value: T): T {
  // The ref object is a generic container whose current property is mutable ...
  // ... and can hold any value, similar to an instance property on a class
  const ref: any = useRef<T>();
  // Store current value in ref
  useEffect(() => {
    ref.current = value;
  }, [value]); // Only re-run if value changes
  // Return previous value (happens before update in useEffect above)
  return ref.current;
}
Run Code Online (Sandbox Code Playgroud)

key可以将值添加到remember函数中,但我发现这remember在我的情况下不起作用,因为即使没有keys传入,它也总是重新渲染。

用法:

/**
 * Returns a dummy MutableState that does not cause render when setting it
 */
@Composable
fun <T> rememberRef(): MutableState<T?> {
    // for some reason it always recreated the value with vararg keys,
    // leaving out the keys as a parameter for remember for now
    return remember() {
        object: MutableState<T?> {
            override var value: T? = null

            override fun component1(): T? = value

            override fun component2(): (T?) -> Unit = { value = it }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


cuo*_*gtd 5

我发现我可以通过使用remember {mutableStateOf}以下方法获得股票行情的最后一个值:

var lastTicker by remember { mutableStateOf(ticker)}

SideEffect {
   if (lastTicker != ticker) {
     // compare lastTicker to current ticker before assign new value
   
     lastTicker = ticker
   }
}
Run Code Online (Sandbox Code Playgroud)

通过使用remember { mutableStateOf(ticker)},我可以通过重组保留股票代码的值。

然后在 SideEffect 中,我可以使用 lastTicker 值(在我的情况下比较最后一个股票代码和当前股票代码),然后将其分配给新值以用于下一个合成

derivedStateOf仅用于观看股票行情变化,避免重组

val compareValue by remember(ticker) {
    derivedStateOf {
        // compare lastTicker to current ticker before assign new value

        lastTicker = ticker
       // return value
    }
}
Run Code Online (Sandbox Code Playgroud)