RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1590028
Accepted
Sirop4ik
Sirop4ik
Asked:2024-08-09 01:28:47 +0000 UTC2024-08-09 01:28:47 +0000 UTC 2024-08-09 01:28:47 +0000 UTC

NavHost 在切换屏幕时连续进行多次重组

  • 772

有这段代码作为重现的最小示例

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Button
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.krokosha.focusrequester2.ui.theme.Test_delete_itTheme

private const val FIRST_SCREEN_ROUTE = "first_screen"
private const val SECOND_SCREEN_ROUTE = "second_screen"

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            Test_delete_itTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    shape = RectangleShape
                ) {
                    Greeting()
                }
            }
        }
    }
}

@Composable
fun Greeting() {
    val navigator: NavHostController = rememberNavController()

    NavHost(
        navController = navigator,
        startDestination = FIRST_SCREEN_ROUTE
    ) {
        composable(FIRST_SCREEN_ROUTE) {
            Log.e("HERE", "1 SCREEN")
            FirstScreen(onClick = { navigator.navigate(SECOND_SCREEN_ROUTE) }) }
        composable(SECOND_SCREEN_ROUTE) {
            Log.e("HERE", "2 SCREEN")
            SecondScreen() }
    }
}

@Composable
fun SecondScreen() {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Red.copy(alpha = 0.1f)),
        contentAlignment = Alignment.Center
    ) {
        Text(text = "SECOND SCREEN")
    }
}

@Composable
fun FirstScreen(onClick: () -> Unit) {
    Row(modifier = Modifier
        .fillMaxSize()
    ) {
        LeftPanel()
        RightPanel(onClick = onClick)
    }
}

@Composable
fun RowScope.LeftPanel() {
    val buttons: List<String> by rememberSaveable { mutableStateOf(List(5) { "Button ${it + 1}" }) }

    LazyColumn(
        modifier = Modifier
            .background(Color.Blue.copy(alpha = 0.1f))
            .fillMaxHeight()
            .weight(1f),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        itemsIndexed(
            items = buttons,
            key = { idx, _ -> idx }
        ) { idx, _ ->
            Button(
                modifier = Modifier,
                onClick = { /* nothing */ }
            ) {
                Text(text = "Left Panel: $idx")
            }
        }
    }
}

@Composable
fun RowScope.RightPanel(onClick: () -> Unit) {
    val buttons: List<String> by rememberSaveable { mutableStateOf(List(4) { "Button ${it + 1}" }) }

    Column(
        modifier = Modifier
            .background(Color.Green.copy(alpha = 0.1f))
            .fillMaxHeight()
            .weight(1f),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        LazyVerticalGrid(
            modifier = Modifier.padding(16.dp),
            columns = GridCells.Fixed(2),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            itemsIndexed(
                items = buttons,
                key = { idx, _ -> idx }
            ) { idx, _ ->
                Button(
                    modifier = Modifier
                        .padding(8.dp),
                    onClick = {
                        onClick()
                    }
                ) {
                    Text(text = "Right Panel: $idx")
                }
            }
        }
    }
}

在此输入图像描述

我离开了登录状态composable(FIRST_SCREEN_ROUTE),composable(SECOND_SCREEN_ROUTE)当我单击右侧面板(屏幕上)中的按钮时,我在日志中看到以下内容(以及 中的相同内容LayoutInspector)

13:26:43.572  E  1 SCREEN
13:26:46.570  E  1 SCREEN
13:26:46.580  E  2 SCREEN
13:26:46.661  E  1 SCREEN
13:26:46.668  E  2 SCREEN
13:26:47.369  E  2 SCREEN
13:26:47.438  E  2 SCREEN

问题是——最空的例子加上最空的导航,切换屏幕时怎么会发生多次重组呢?

android
  • 1 1 个回答
  • 24 Views

1 个回答

  • Voted
  1. Best Answer
    Wlad
    2024-08-09T14:02:56Z2024-08-09T14:02:56Z

    你有日志的地方有点错误。
    当更改 UI 时,重组始终会转到最重要的父元素。
    然后它开始向下遍历孩子并检查他们的参数。如果它们发生了变化,孩子们就会重新组合。
    在您的情况下(移动到新屏幕)您有一个重新组合的方法Greeting,即它将被完全重新调用,这就是日志如此工作的原因。

    所以首先您需要在函数内传输日志FirstScreen并SecondScreen

    现在我们看到这些函数被可疑地重绘了很多次。
    问题就在这个地方:
    FirstScreen(onClick = { navigator.navigate(SECOND_SCREEN_ROUTE) }) }
    事实是你的点击代码不稳定。

    要解决这个问题,你可以这样写:

    @Composable
    fun Greeting() {
        val navigator: NavHostController = rememberNavController()
    
        val click = remember { { navigator.navigate(SECOND_SCREEN_ROUTE) } }
    
        NavHost(
            navController = navigator,
            startDestination = FIRST_SCREEN_ROUTE
        ) {
    
    
            composable(FIRST_SCREEN_ROUTE) {
                FirstScreen(onClick = { click() })
            }
            composable(SECOND_SCREEN_ROUTE) {
                SecondScreen()
            }
        }
    }
    

    现在点击很稳定,并且确实不会发生不必要的重组。

    • 1

相关问题

  • 来自片段的列表落后于 BottomNavigationView

  • 无法将变量从 Activity 传递到 Fragment

  • 构建与完成的片段略有不同的片段的最佳方法是什么?

  • 如何更改来自服务器的响应中的日期格式?

  • 谷歌地图在应用程序的发布版本中不起作用

  • 材料设计按钮。单击按钮上的可选区域!

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5