标签: compose-recomposition

@Stable 和 @Immutable 注释在 Jetpack Compose 中意味着什么?

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

据我了解,如果使用@Immutable,即使状态改变,也不应该发生重组。然而,作为测试的结果,重组仍在继续。

@StableJetpack Compose 中注释的具体作用是什么@Immutable

android android-jetpack-compose compose-recomposition

51
推荐指数
2
解决办法
2万
查看次数

Jetpack Compose NavHost 重组可组合多次

我发现可组合屏幕在 Navhost 导航期间多次重新组合,以下示例显示了我如何将导航与日志集成以识别函数被调用的次数,

internal sealed class Screen(val route: String) {
  object Splash : Screen("splash")
  object Login : Screen("login")
  object Credentials : Screen("credentials/{type}") {
    fun createRoute(type: String) = "credentials/$type"
  }
}

@Composable
fun HostNavGraph(
  modifier: Modifier = Modifier,
  startDestination: String = Splash.route,
) {
  val navController = rememberNavController()
  val vm: CredentialsViewModel = getViewModel()
  NavHost(navController = navController, startDestination = startDestination, modifier = modifier) {
    composable(route = Splash.route) {
      Log.e("composable", " Splash")
      SplashScreen(openLogin = {
        navController.navigate(Login.route)
      }, openRegistration = { type ->
        navController.navigate(Credentials.createRoute(type)) …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-navigation android-jetpack-compose jetpack-compose-navigation compose-recomposition

26
推荐指数
1
解决办法
5847
查看次数

Jetpack Compose 中的 Remember 和 RememberUpdatedState 之间的区别?

我很困惑,有人可以向我解释一下两者之间的区别吗:

val variable by remember { mutableStateOf() }
Run Code Online (Sandbox Code Playgroud)

val variable by rememberUpdatedState()
Run Code Online (Sandbox Code Playgroud)

当我检查源代码时,rememberUpdatedStates我实际上看到:remember { mutableStateOf() }

@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose compose-recomposition

25
推荐指数
2
解决办法
1万
查看次数

Jetpack Compose:布局检查器未显示重组计数菜单

Android Studio 大黄蜂补丁 3

从这个页面,它说我可以看到重组计数: https: //developer.android.com/jetpack/compose/tooling#recomposition-counts

它没有向我显示菜单选项。仅设备名称和“停止检查器”

android layout-inspector android-jetpack android-jetpack-compose compose-recomposition

22
推荐指数
3
解决办法
8666
查看次数

Jetpack Compose 范围/智能重组

我正在做实验来理解重组和智能重组并制作了一个样本

\n

在此输入图像描述

\n

抱歉,颜色是用 Random.nextIn() 生成的,以便在视觉上观察重组,设置颜色对重组没有影响,也尝试不更改颜色。

\n

gif的内容由三部分组成

\n

样品1

\n
@Composable\nprivate fun Sample1() {\n\n    Column(\n        modifier = Modifier\n            .background(getRandomColor())\n            .fillMaxWidth()\n            .padding(4.dp)\n    ) {\n        var counter by remember { mutableStateOf(0) }\n\n\n        Text("Sample1", color = getRandomColor())\n\n        Button(\n            modifier = Modifier\n                .fillMaxWidth()\n                .padding(vertical = 4.dp),\n            colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),\n            onClick = {\n                counter++\n            }) {\n            Text("Counter: $counter", color = getRandomColor())\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我在这里没有问题,因为智能组合按预期工作,Text最重要的是不读取更改,counter因此重组仅发生在Textinside Button

\n

样品2

\n
@Composable\nprivate fun Sample2() {\n    Column(\n        modifier …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose compose-recomposition

16
推荐指数
1
解决办法
7253
查看次数

由于 Lazycolumn Jetpack compose 中的 IndexOutOfBoundsException 导致应用程序崩溃

当我删除 mutableStateListOf 中的项目时,我收到 IndexOutOfBoundsException,其中 MyType 是某种自定义类型。myList 中有大约 250 项。这些项目将循环删除。几乎 6 个元素同时在视口中可见。当项目计数达到小于或等于 6(滚动位置位于顶部)时,会引发此异常并且应用程序崩溃。

此外,仅当 Listview 为活动屏幕时应用程序才会崩溃。否则它不会崩溃/不会引发此索引出界异常。我已经调试了应用程序逻辑,并确保进行检查以忽略索引大于列表大小的任何更新/添加/删除请求。我怀疑仅在重组期间引发异常。我观察到的另一个行为是,当列表滚动到底部并且项目被删除时,则在循环的最开始就已经引发了此异常。请查看堆栈跟踪。

FATAL EXCEPTION: main Process: com.XXX.YYY.ZZZ, PID: 16225 java.lang.IndexOutOfBoundsException: Index 6, size 6 at androidx.compose.foundation.lazy.layout.MutableIntervalList.checkIndexBounds(IntervalList.kt:177) at androidx.compose.foundation.lazy.layout.MutableIntervalList.get(IntervalList.kt:160) at androidx.compose.foundation.lazy.layout.DefaultLazyLayoutItemsProvider.getKey(LazyLayoutItemProvider.kt:232) at androidx.compose.foundation.lazy.LazyListItemProviderImpl.getKey(Unknown Source:2) at androidx.compose.foundation.lazy.layout.DefaultDelegatingLazyLayoutItemProvider.getKey(LazyLayoutItemProvider.kt:201) at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProvider$1$1.getKey(Unknown Source:2) at androidx.compose.foundation.lazy.LazyMeasuredItemProvider.getAndMeasure-ZjPyQlc(LazyMeasuredItemProvider.kt:46) at androidx.compose.foundation.lazy.LazyListMeasureKt.measureLazyList-Hh3qtAg(LazyListMeasure.kt:164) at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke-0kLqBqw(LazyList.kt:299) at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke(LazyList.kt:190) at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$1$2$1.invoke-0kLqBqw(LazyLayout.kt:71) at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$1$2$1.invoke(LazyLayout.kt:69) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:598) at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:103) at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:635) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:155) at androidx.compose.foundation.layout.SizeModifier.measure-3p2s80s(Size.kt:781) at androidx.compose.ui.node.BackwardsCompatNode.measure-3p2s80s(BackwardsCompatNode.kt:323) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:155) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1090) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1086) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200) at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234) at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230) at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341) at …

indexoutofboundsexception compose-recomposition android-jetpack-compose-lazy-column

15
推荐指数
1
解决办法
2135
查看次数

Jetpack Compose @Stable List&lt;T&gt; 参数重组

@Composable 函数被重构

  • 如果参数发生变化或者
  • 如果参数之一不是@Stable/@Immutable

items: List<Int>作为参数传递时,compose 总是重新组合,无论是否List是不可变的且无法更改。(List是没有@Stable注解的接口)。因此,任何接受List<T>参数的可组合函数总是会被重组,而不是智能重组。

如何标记List<T>为稳定,以便编译器知道 List 是不可变的并且函数永远不需要因此而重新组合?

我发现的唯一方法就是像这样包裹@Immutable data class ImmutableList<T>(val items: List<T>)。演示(当 Child1 重组 Parent 时,具有相同 List 的 Child2 也会被重组)

class TestActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeBasicsTheme {
                Parent()
            }
        }
    }
}

@Composable
fun Parent() {
    Log.d("Test", "Parent Draw")
    val state = remember { mutableStateOf(false) }
    val items = remember { listOf(1, 2, 3) …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-compose compose-recomposition

12
推荐指数
1
解决办法
5580
查看次数

Compose - NavHost 多次重组

在 Navhost 导航期间,我发现可组合屏幕多次重新组合。因此,我的 ViewModel 也多次调用 API 数据源。

@Composable
fun MainView() {
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))
    val scope = rememberCoroutineScope()
    val navController = rememberNavController()
    Scaffold(
        scaffoldState = scaffoldState,
        topBar = { TopBar(
            toolbarTitle = stringResource(id = R.string.app_name),
            scope = scope,
            scaffoldState = scaffoldState
        ) },
        drawerContent = {
           DrawerView(scope = scope, scaffoldState = scaffoldState, navController = navController)
        },
    ) {
        NavGraph(navController = navController)
    }
}

@Composable
fun NavGraph(navController: NavHostController) {
    NavHost(navController, startDestination = NavDrawerItem.Repositories.route) {
        composable(NavDrawerItem.Repositories.route) {
            RepoListView(getViewModel())
        }

        composable(NavDrawerItem.EmojiList.route) { …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-navigation android-jetpack-compose jetpack-compose-navigation compose-recomposition

12
推荐指数
1
解决办法
6053
查看次数

Jetpack Compose 惰性列在单个项目更新时重新组合所有项目

我正在尝试执行一些列表操作,但遇到了单个项目更新时所有项目重新组合的问题。

https://prnt.sc/8_OAi1Krn-qg

我的模特;

data class Person(val id: Int, val name: String, val isSelected: Boolean = false)

@Stable
data class PersonsWrapper(val persons: List<Person>)
Run Code Online (Sandbox Code Playgroud)

我的ViewModel和更新功能;

private val initialList = listOf(
    Person(id = 0, name = "Name0"),
    Person(id = 1, name = "Name1"),
    Person(id = 2, name = "Name2"),
    Person(id = 3, name = "Name3"),
    Person(id = 4, name = "Name4"),
    Person(id = 5, name = "Name5"),
    Person(id = 6, name = "Name6"),
)

val list = mutableStateOf(PersonsWrapper(initialList))

fun updateItemSelection(id: Int) {
    val …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-compose compose-recomposition android-jetpack-compose-lazy-column

11
推荐指数
1
解决办法
7681
查看次数

为什么 ViewModel 方法引用不稳定(导致重组),而 lambda 却稳定?(Jetpack 撰写)

我有一个 MVI 架构,其中包含主屏幕的活动

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      MyTheme {
        val viewModel: MainScreenViewModel = viewModel(factory = MainScreenViewModel.Factory)
        val state by viewModel.viewState.collectAsState()
        MainScreen(state, viewModel::handleEvent)
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

主屏幕看起来有点像这样:

@Composable
fun MainScreen(state: MainScreenState, onEvent: (Event) -> Unit) {
  TaskList(
    tasks = state.items,
    onEvent = onEvent,
  )
}

@Composable
fun TaskList(tasks: List<TaskState>, onEvent: (Event) -> Unit) {
  LazyColumn {
    items(items = tasks, key = { it.id }) {
      Task(state = it, onEvent = onEvent) …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose compose-recomposition

11
推荐指数
1
解决办法
912
查看次数