标签: compose-recomposition

Compose Accompanist Pager 中的 TabRow/Tab 重组问题

我试图在 Jetpack compose 中创建一个示例选项卡视图,因此结构将类似于在父选项卡行内部,我们正在迭代选项卡标题并创建选项卡可组合项。

更精确的代码将是这样的。

@OptIn(ExperimentalPagerApi::class)
@Composable
private fun MainApp() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(stringResource(R.string.app_name)) },
                backgroundColor = MaterialTheme.colors.surface
            )
        },
        modifier = Modifier.fillMaxSize()
    ) { padding ->
        Column(Modifier.fillMaxSize().padding(padding)) {
            val pagerState = rememberPagerState()
            val coroutineScope = rememberCoroutineScope()
            val tabContents = listOf(
                "Home" to Icons.Filled.Home,
                "Search" to Icons.Filled.Search,
                "Settings" to Icons.Filled.Settings
            )
            HorizontalPager(
                count = tabContents.size,
                state = pagerState,
                contentPadding = PaddingValues(horizontal = 32.dp),
                modifier = Modifier
                    .weight(1f)
                    .fillMaxWidth()
            ) { page ->
                PagerSampleItem(
                    page …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose jetpack-compose-accompanist compose-recomposition

6
推荐指数
1
解决办法
1616
查看次数

Jetpack Compose,使用自定义 Lifecycle/ViewModelStore/SavedStateRegistry Owner 时不会触发重组

我正在尝试创建一个覆盖层并将视图附加到 WindowManager,我已经通过创建一个实现 Lifecycle/ViewModelStore/SavedStateRegistry Owner 的类来设法做到这一点。\n但由于某种原因,每当我尝试显示对话框/更改时以任何方式使用 MutableState 或 MutableStateFlow 重组的 UI 都不会触发。

\n

有没有人尝试过做这样的事情并设法找到触发重组的解决方案?

\n

这就是我尝试创建和插入视图的方式:

\n
@SuppressLint("InflateParams")\nfun showOverlay() {\n    synchronized(lock) {\n        if (overlay != null || overlay?.parent != null) {\n            return\n        }\n        val viewModel = OverlayViewModel(context.applicationContext as Application)\n        var scope: CoroutineScope? = null\n        overlay = ComposeView(context).apply {\n            setContent {\n                Overlay(viewModel)\n            }\n        }\n        drawOverLifecycleOwner = DrawOverLifecycleOwner()\n        drawOverLifecycleOwner?.attachToDecorView(overlay)\n        val params =\n            WindowManager.LayoutParams(\n                WindowManager.LayoutParams.MATCH_PARENT,\n                WindowManager.LayoutParams.MATCH_PARENT,\n                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,\n                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,\n                PixelFormat.TRANSLUCENT\n            )\n        params.gravity = Gravity.TOP or Gravity.START\n        Log.i("ScreenLocker", "Inserting overlay")\n        ContextCompat.getMainExecutor(context).execute {\n …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose compose-recomposition

5
推荐指数
1
解决办法
1326
查看次数

Jetpack Compose,使用 NavHost 导航时可变状态会导致无限重组

这是导致无限重组问题的代码

主要活动

class MainActivity : ComponentActivity() {
    
     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        setContent {
                val navController = rememberNavController()
                val viewModel : MainViewModel by viewModel()
                val state by viewModel.state.observeAsState()

                NavHost(navController = navController, startDestination = "firstScreen") {
                    composable("firstScreen") { FirstScreen(
                        navigate = {
                        navController.navigate("secondScreen")
                    }, updateState = {
                            viewModel.getState()
                       },
                       state

                    )}

                    composable("secondScreen") { SecondScreen() }
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型

class MainViewModel : ViewModel() {

    //var state = MutableStateFlow(0)

    private val _state = MutableLiveData(0)
    val state: LiveData<Int> = _state

    fun …
Run Code Online (Sandbox Code Playgroud)

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

5
推荐指数
1
解决办法
1781
查看次数

更改列表项类中的属性值时,Jetpack compose mutableStateOf 列表不会触发重新组合

我认为我在这里缺少 Jetpack Compose 的核心概念。non-constructor data class property当我尝试更改可组合项的内部且此可组合项是观察列表的一部分时,我遇到了问题。

不起作用:(sadProperty未在构造函数中声明)

data class IntWrapper(val actualInt: Int = 0) {
var sadProperty: Int = 0
}

@Preview
@Composable
fun test() {
var state by remember { mutableStateOf(listOf(IntWrapper(1), IntWrapper(2), IntWrapper(3),IntWrapper(4)))}

    fun onClick(item: IntWrapper) {
        val indexOf = state.indexOf(item)
        val newState = state.minus(item).toMutableList()
        val copy = item.copy()
        copy.sadProperty = Random.nextInt()
        newState.add(indexOf, copy)
        state = newState
    }
    
    Column() {
        for (item in state) {
            Text("ac: ${item.actualInt} sad: ${item.sadProperty}", modifier = Modifier.clickable { onClick(item)}) …
Run Code Online (Sandbox Code Playgroud)

android kotlin data-class android-jetpack-compose compose-recomposition

5
推荐指数
1
解决办法
1911
查看次数

Jetpack Compose 重组竞争条件

假设我们有以下代码。它显示一个按钮,当用户单击它时,该按钮就会消失。

@Composable
fun ButtonThatDisappearsOnClick() {
    var showButton by remember { mutableStateOf(true) }
    if (showButton) {
        Button(onClick = {
            check(showButton) { "onClick shouldn't be called for a hidden button" }  // !!!
            showButton = false
        }) {
            Text("My button")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我怀疑check如果用户快速单击按钮两次,上面的调用可能会失败:

  • 用户点击按钮,shouldShowButton设置为false。由于可变状态下的值已更新,因此安排了重组。
  • 在视图重新组合之前,用户再次快速单击该按钮。因此,该onClick函数将第二次触发,并且check调用将失败。

我无法在实践中重现这一点,所以我想知道这种行为是否确实可能。

android race-condition kotlin android-jetpack-compose compose-recomposition

5
推荐指数
1
解决办法
886
查看次数

Jetpack 撰写惰性列不与列表重新组合

我有一个存储在Viewmodelvia内的列表Stateflow

class FirstSettingViewModel : ViewModel() {

     private val _mRoomList = MutableStateFlow<List<InitRoom>>(mutableListOf())
     val mRoomList: StateFlow<List<InitRoom>> = _mRoomList
    
     ...
Run Code Online (Sandbox Code Playgroud)

我通过 观察流程collectAsState()。它LazyColumn由可以单击的框组成。

val roomList = mViewModel.mRoomList.collectAsState()

Dialog {

    ...

    LazyColumn(...) {

        items(roomList.value, key = { room -> room.room_seq}) { room ->
          
           Box(Modifier.clickable {
              **mViewModel.selectItem(room)**
           }) {...}
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

当单击事件发生时,viewModel 通过复制列表更改“isSelected”值,如下所示。

fun selectItem(room: InitRoom) = viewModelScope.launch(Dispatchers.IO) {
    try {
        val cpy = mutableListOf<InitRoom>()
        mRoomList.value.forEach {
            cpy.add(it.copy())
        }
        cpy.forEach {
            it.isSelected = it.room_seq == room.room_seq
        } …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-compose kotlin-stateflow lazycolumn compose-recomposition

5
推荐指数
1
解决办法
1924
查看次数

从列表中删除项目会导致 LazyColumn 中显示错误

我认为这是一个奇怪的情况。Textfields我正在显示a 中的列表LazyColoumn。用户可以删除每个文本字段,但这样做时,它会复制 REPLACE 文本字段中的值。

移除前

移除后

发生了什么:

我添加了 3 个人:第 1 人、第 2 人、第 3 人

我单击“删除人员 2”。

人员 3 现在位于人员 2 的位置(参见名称),但复制了人员 2 的 VALUE。

我这样管理状态:

private val peopleStateFlow = MutableStateFlow<List<Person>>()
Run Code Online (Sandbox Code Playgroud)

我像这样加载该列:

val peopleState = viewModel.peopleState.collectAsState()
LazyColumn {
    val peopleStateSnap = peopleState.value
    items(peopleStateSnap.size) { index ->
    val person = peopleStateSnap[index]
    ParticipantView(
        person = person,
        sharedOwed = sharedOwed.value,
        onChangeListener = {
            viewModel.updateOwed(person, it)
        },
        onRemoveClicked = {
            viewModel.removePerson(person)
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

我这样删除这个人:

fun removePerson(person: Person) {
        val indexOf …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose lazycolumn compose-recomposition

5
推荐指数
1
解决办法
1041
查看次数

ViewModel 使用 JetpackCompose 触发导航

在 Android 中,我经常想要导航以响应 ViewModel 的状态更改。(例如,成功的身份验证会触发导航到用户的主屏幕。)

最佳实践是从 ViewModel 内触发导航吗?是否有有意的机制来触发可组合项中的导航以响应 ViewModel 状态更改?

使用 Jetpack Compose 处理此用例的过程并不明显。如果我尝试类似以下示例的操作,将会发生导航,但我导航到的目的地将无法正常运行。我相信这是因为在调用导航之前不允许完成原始的可组合函数。

// Does not behave correctly.
@Composable fun AuthScreen() {
    val screenState = viewModel.screenState.observeAsState()
    if(screenState.value is ScreenState.UserAuthenticated){
        navController.navigate("/gameScreen")
    } else {
        LoginScreen()
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用 LaunchedEffect ,我确实会观察到正确的行为,如下所示:

// Does behave correctly.
@Composable fun AuthScreen() {
    val screenState = viewModel.screenState.observeAsState()
    if(screenState.value is ScreenState.UserAuthenticated){
        LaunchedEffect(key1 = "test") {
            navController.navigate("$/gameScreen")
        }
    } else {
        LoginScreen()
    }
}
Run Code Online (Sandbox Code Playgroud)

它是否正确?LaunchedEffect 的文档说明如下,但我并不是 100% 清楚其含义:

当 LaunchedEffect 进入组合时,它将启动块到组合的 CoroutineContext 中。当 LaunchedEffect 用不同的 key1、key2 或 …

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

5
推荐指数
1
解决办法
1319
查看次数

从 Firestore 获取单词不会更新 LazyColumn Jetpack Compose

@Composable
fun getData() {
        var wordData = arrayListOf<Word>()
        db.get().addOnSuccessListener { documents ->
            for (document in documents) {
                wordData.add(document.toObject(Word::class.java))
            }
        }
        LazyColumn {
            items(wordData) {  word ->
                WordCard(word = word)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我想使用 Lazy Column 显示我所有的单词数据,这些是我的 WordCard 代码。

@Composable
fun WordCard(word: Word) {
    Text(text = word.word, color = Color.Black, modifier = Modifier.background(Color.Gray).padding(12.dp))
}
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose lazycolumn compose-recomposition

5
推荐指数
1
解决办法
260
查看次数

撰写警报对话框未关闭

我有一个对话框,当我按下按钮时我无法关闭这是我的代码,我相信这是用于 if 循环的,但我需要它在这种情况下使其成为现实,有什么想法可以帮助我吗?

\n
@Composable\n    fun PopupWindowDialog(\n    parentUiState: ParentHomeUiState,\n) {\n    val openDialog = remember { mutableStateOf(false) }\n    var sliderPosition by remember { mutableStateOf(0f) }\n\n    if (!parentUiState.showInAppFeedback){\n        openDialog.value = true\n    }\n    val recommend = sliderPosition.toInt()\n    Column(\n    ) {\n        Box {\n            if (openDialog.value) {\n                Dialog(\n                    onDismissRequest = { openDialog.value = false },\n                    properties = DialogProperties(),\n                ){\n                    Box(\n                        Modifier\n                            .fillMaxWidth()\n                            .fillMaxHeight()\n                            //.padding(vertical = 70.dp, horizontal = 10.dp)\n                            .padding(vertical = 70.dp )\n                            .background(Color.White, RoundedCornerShape(10.dp))\n                            //.border(1.dp, color = Color.Black, RoundedCornerShape(20.dp))\n                            .border(1.dp, color = Color.White, RoundedCornerShape(20.dp))\n …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose compose-recomposition

5
推荐指数
1
解决办法
1167
查看次数