Skip to content

迁移到hooks2 的说明

Junerver Hou edited this page Dec 2, 2024 · 8 revisions

从 hooks 迁移到 kmp 版本的 hooks2 有以下注意事项:

1. optionsOf 废弃

如果你在需要使用配置的hooks中直接使用使用了optionsOf,并且没有使用命名参数 :

val (resume, pause, isActive) = useInterval(
    optionsOf {
        initialDelay = 2.seconds
        period = 1.seconds
    }
) 

需要修改为:

val (resume, pause, isActive) = useInterval(
    optionsOf = {
        initialDelay = 2.seconds
        period = 1.seconds
    }
)

RequestOptions的参数 debounceOptionsthrottleOptions,需要替换为各自的 optionOf 函数:

  • DebounceOptions.optionOf { }
  • ThrottleOptions.optionOf { }

或者使用新的参数:debounceOptionsOfthrottleOptionsOf,在未来版本将会将实力参数修改为 internal 访问

替换:

第一步替换 debounceOptionsthrottleOptions

  • debounceOptions = optionsOf { 替换为 debounceOptions = DebounceOptions.optionOf {
  • throttleOptions = optionsOf { 替换为 throttleOptions = ThrottleOptions.optionOf {

第二步:全局替换 options = optionsOf {optionsOf = {

第三步:替换 optionsOf {optionsOf = {

2. defaultOptionOptions.default()移除

这个函数几乎不应该在用户侧调用,因为所有需要默认参数的函数都已经赋值,如果你现在确实需要一个默认的选项对象

使用Options.optionOf{}

3. 纯 Android 项目

纯Android项目请使用如下依赖:

implementation("xyz.junerver.compose:hooks2-android:<latest_release>")

4. 破坏性更新

在过去的版本为了使用方便,大多数的api都是直接返回了状态的值,这很方便,但是也带来了一些潜在的性能问题,例如下面的代码:

@Composable
private fun TestDeferReads() {
    var byState by useState("default1")
    val (state,setState,getState) = useGetState("getState")
    
    Column(modifier = Modifier.randomBackground().size(200.dp, 300.dp)) {
        //by委托
        Button(onClick = {
            byState+="1"
        }) { Text(byState) }
        //triple 解构
        Button(onClick = {
            setState(getState()+"2")
        }) { Text(state) }
    }
}

现象:

我们点击第一个按钮,Column的背景色不会发生改变,说明该组件没有发生重组。当我们点击第二个按钮时,Column 组件背景色发生变化,证明其发生了重组。

原因:

原因很简单,在 Compose 中读取状态的操作才是真正触发重组的关键,只有读取State,组件才会因为State变化而进入了重组,如果只是声明了State而没有直接读取State的值,State变化后是不会导致当前组件重组的。

在一些复杂的页面中必然存在大量的类似 Column 这样的内联组件,在一个复杂的组件树中,这样的重组可能会带来性能问题。

所以在 hooks2 中将不再直接返回 状态的值(不在hook调用处触发读取),而是返回只读状态本身,在组件中需要值时,通过 state.value 获取(延迟读取)

简而言之,hook将从返回状态值T,修改成返回状态State<T>

涉及到的hooks

涉及的 hooks :

  • useGetState
  • useBoolean
  • useCounter
  • useCountdown
  • useDebounce
  • useResetState
  • useReducer
  • useSelector
  • useTimestamp
  • useInterval
  • uesThrottle
  • usePrevious
  • useUndo
  • useNow
  • useRequest

对于返回元组的,你需要修改代码为 state.value,来使用状态的值。对于 useDebounceuesThrottleuseSelector 等只返回状态的,可以简单的通过修改 =by

例如:

// 修改前
val (state, setState, getState) = useGetState("getState")
Column(modifier = Modifier.randomBackground().size(200.dp, 300.dp)) {
    Button(onClick = {
        setState(getState() + "1")
    }) { Text(state) } //此处可以直接使用state的值
}

// 修改后
val (state, setState, getState) = useGetState("getState")
Column(modifier = Modifier.randomBackground().size(200.dp, 300.dp)) {
    Button(onClick = {
        setState(getState() + "2")
    }) { Text(state.value) } //改为 state.value
}

5. SetValueFn<T> -> SetValueFn<SetterEither<T>>

SetValueFn改版


6.减少对元组类型的使用

kotlin 官方只有Pair、Triple 这两个元组类型,在过去的项目中使用的是 Arrow-KT 提供的元组类型,基于的都是 data class 内置的解构声明

在解构使用中,kt提供的解构能力较弱,可读性也很差,鉴于 kotlin conf 24 承诺未来会提供更好的基于名称解构。

目前,在 hooks2 中已经将返回值由元组类暂时修改为更可读的 XxxHolder

7.示例

请参考迁移示例

Clone this wiki locally