8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

Jetpack Compose 中的 @Stable 和 @Immutable 注释是什么意思?

Asad Ali 2月前

96 0

在研究 Jetpack Compose 示例项目时,我看到了 @Stable 和 @Immutable 注释。我一直在浏览 Android 文档和 GitHub 上有关这些注释的内容,但我确实……

在研究 Jetpack Compose 示例项目时,我看到了 @Stable 注释 @Immutable 。我一直在 Android 文档 and GitHub 有关这些注释的信息,但我不明白。

据我了解,如果使用 @Immutable ,即使状态发生变化,也不应该发生重组。但是,测试的结果是,重组仍在进行。

Jetpack Compose 中的注释 @Stable 到底 @Immutable 起什么作用

帖子版权声明 1、本帖标题:Jetpack Compose 中的 @Stable 和 @Immutable 注释是什么意思?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Asad Ali在本站《android》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 定义

    @Immutable 是一个注释,用于告诉 Compose 编译器此对象对于优化来说是不可变的,因此如果不使用它,可能会触发不必要的重新组合。

    @Stable 是另一个注释,用于告诉 Compose 编译器此对象可能会发生变化,但当它发生变化时,Compose 运行时将收到通知。

    如果你读到这里,可能还不太明白。所以需要更多解释...


    Compose 指标报告

    当您生成 Compose 指标报告 ,它会将对象标记为 stable or unstable ,对于 unstable 对象,Compose 编译器无法判断对象是否被修改,因此无论如何它都必须触发重组。以下是报告的两个片段:

    restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SomeClass1(
      stable modifier: Modifier? = @static Companion
    )
    
    restartable scheme("[androidx.compose.ui.UiComposable]") fun SomeClass2(
      stable modifier: Modifier? = @static Companion
      stable title: String
      unstable list: List<User>
      stable onClicked: Function1<User>, Unit>
    )
    

    需要可跳过!

    在 的情况下 SomeClass1 ,它被标记为 skippable ,因为它的所有参数都标记为 stable 。对于 SomeClass2 ,它不会被标记为 skippable 一个 list 属性 unstable .

    当它被标记为 时 skippable ,这是一件好事,因为 Compose 编译器可以尽可能地跳过重组,并且更加优化。

    什么情况下无法将其标记为可跳过?

    通常,compose 编译器足够聪明,能够推断出什么是 stable 和什么是 unstable 。在 compose 编译器无法判断稳定性的情况下,它们是可变对象,例如包含 var 属性的类。

    class SomeViewState {
      var isLoading: Boolean
    }
    

    另一种无法确定稳定性的情况是像这样的类 Collection ,例如 List ,因为即使接口 List 看起来是不可变的,它实际上也可以是一个可变列表。例如:

    data class SomeViewState {
        val list: List<String>
    }
    @Composable
    fun ShowSomething(data: SomeViewState) {
    }
    

    尽管上面的 Composable 接受 SomeViewState 其所有属性为 val ,但它仍然是 unstable 。你可能想知道为什么?这是因为在使用方面,你实际上可以将它与 一起使用 MutableList ,如下所示:

    ShowSomething(SomeViewState(mutableListOf()))
    

    因此,编译器必须将其标记为 unstable .

    因此在这种情况下,我们想要实现的是 stable 重新制作它们,以便对它们进行优化。


    @Stable 和 @Immutable

    有两种方法可以 stable 再次制作,分别是使用 @Stable @Immutable .

    使用 @Stable ,如上所述,这意味着可以更改值,但是当它确实发生变化时,我们必须通知 Compose 编译器。实现方法是通过使用 mutableStateOf()

    @Stable
    class SomeViewState {
      var isLoading by mutableStateOf(false)
    }
    

    使用 @Immutable ,意味着当您将数据传递到 Composable 时,您将始终生成数据的新副本,换句话说,您承诺数据是不可变的。从上面的例子来看:

    @Immutable
    data class SomeViewState {
        val list: List<String>
    }
    @Composable
    fun ShowSomething(data: SomeViewState) {
    }
    

    在使用 进行注释后 @Immutable ,在使用方面,您应该确保创建一个新列表,而不是直接改变列表。

    示例 DO:

    class ViewModel {
        val state: SomeViewState = SomeViewState(listOf())
        fun removeLastItem() {
            val newList = state.list.toMutableList().apply {
                    removeLast()
                }
            state = state.copy(
                list = newList
            )
        }
    }
    

    例如不要做的事情:

    class ViewModel {
        val state: SomeViewState = SomeViewState(mutableListOf())
        fun removeLastItem() {
            state.list.removeLast() // <=== you violate your promise of @Immutable!
        }
    }
    

    为了更深入地了解,您可以阅读以下链接:

    • https://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8
    • https://chrisbanes.me/posts/composable-metrics/
  • 在 @Immutable SomeViewState 示例中,您还可以使用 Kotlin 官方的 Immutable Collections Library (alpha) PersistentList 实现,例如 val list: PersistentList= persistentListOf()。这样,您就不需要在 ViewModel 中提供自己的列表修改实现,因为 PersistentList 会负责复制(甚至可以共享底层数据结构以提高效率)。

  • 可能从 Chris Banes 那里弄错了链接 - chrisbanes.me/posts/composable-metrics

  • 编译器对两者的处理方式相同,但是

    • 使用 @Immutable 是价值永远不会改变的承诺。
    • 使用 @Stable 承诺,即该值是可观察的,并且如果它确实发生了变化,则会通知监听器。
  • sci9 2月前 0 只看Ta
    引用 6

    @JimOvejera - 他们让 Compose 编译器进行一些优化,从而产生更小、更快的重组逻辑。

  • 您能给我们提供一些 @Stable 的自定义实现吗?(除了像 Color 等 Compose 内置函数之外)

  • @Farid - 当状态未发生改变时,组合会跳过可组合项。有时它可以推断事物本身并未发生变化。注释 @Immutable 和 @Stable 可帮助它针对可能触发重组的对象执行此操作。例如,请参阅 medium.com/androiddevelopers/... 或 jetpackcompose.app/articles/...。

  • 例如,为什么 Color 被标记为@Stable 而不是@Immutable?

返回
作者最近主题: