kotlin - Jetpack Compose - 重组时遇到问题

标签 kotlin android-jetpack-compose viewmodel kotlin-stateflow

我正在使用 ViewModel 来存储数据。 ViewModel 有一个包含用户列表的 StateFlow 类。还有一个 donut:Int 字段。

在 Compose 中,当我单击“ donut ”按钮时,变量“ donut ”就会递增,并且重组成功 - 按钮“ donut ”上的数据立即发生变化。 在“用户”按钮上,当我单击时,“用户”列表中的数据会更改(通过 logcat 查看),但不会发生重组。但如果之后我按下 donut 按钮,那么屏幕上的用户数据会立即更改为更改后的数据。 my screen

我的MainViewModel:

class MainViewModel() : ViewModel() {

    private var _usersClass = MutableStateFlow(UsersClass())
    val usersClass: StateFlow<UsersClass> = _usersClass.asStateFlow()

    fun addDonut(int: Int) {
        _usersClass.update {
            it.copy(
                donuts = int
            )
        }
    }

    fun addAgeForAll(){
        val newList = _usersClass.value.userList
        newList.value.forEach(){a->a.addAge()}
        _usersClass.update{
            it.copy(
                userList = newList
            )
        }
    }
}

我的用户类:

data class UsersClass(
    var donuts: Int = 0,

    private var _userList: MutableStateFlow<MutableList<User>> = MutableStateFlow(initData.items.toMutableList()),
    var userList: StateFlow<List<User>> = _userList.asStateFlow()
)

data class User(
    var username: String = "John Doe",
    var age: Int = 18
) {
    fun addAge() {
        age++
    }
}

object initData {
    var items = arrayListOf(
        User(username = "Elvis", age = 18),
        User(username = "Sunny", age = 19),
        User(username = "Mary", age = 18)
    )
}

主要事件:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]

        setContent {
            MainScreen(
                mainViewModel = mainViewModel,
                onClickButtonAddDonut = {
                    mainViewModel.addDonut(mainViewModel.usersClass.value.donuts + 1)
                }
            )
        }
    }
}

@Composable
fun MainScreen(
    mainViewModel: MainViewModel,
    onClickButtonAddDonut: () -> Unit,
) {
    val class1 = mainViewModel.usersClass.collectAsState()
    Column {
        LazyColumn {
            itemsIndexed(class1.value.userList.value) { _, item ->
                Button(
                    onClick = { mainViewModel.addAgeForAll() }
                ) {
                    Text(text = item.toString())
                }

            }
        }

        Button(
            modifier = Modifier,
            onClick = { onClickButtonAddDonut() },
            content = {
                Text(text = "donuts= ${class1.value.donuts}")
            })

    }
}

为什么重组没有发生?我究竟做错了什么?我一周都搞不明白:( 谢谢

最佳答案

问题就在这里

fun addAge() {
    age++
}

这不会通知 Compose 有任何更改,因为它直接改变 age 的值。

一般来说,通过状态流发送的数据应该是不可变的。为此,您可以将 User 更改为,

data class User(
    val username: String = "John Doe",
    val age: Int = 18
)

UserClass是,

data class UsersClass(
    val donuts: Int = 0,
    val userList: List<User> = emptyList()
)

请注意使用 val 而不是 var

经过这些更改,模型上的方法可以是,

fun addAgeForAll(){
    val newList = _usersClass.value.userList.map {
      it.copy(age = it.age + 1)
    }
    _usersClass.update{
        it.copy(
            userList = newList
        )
    }
}

我建议您保持模型简单,就像这样,直到您知道需要额外的流程来防止跳帧。

关于kotlin - Jetpack Compose - 重组时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76529606/

相关文章:

android - Jetpack Compose - 在自定义布局中获取点击位置

java - 测试 Spring 的 @Async void-returning 方法

android - 如何在 VerticalScroller(android 开发人员撰写)中显示指标?

validation - 关于构建 asp.net mvc 应用程序的建议

windows-phone-7 - 在 WP7 中使用 Caliburn.Micro 将 View 模型共享到多个 View

c# - AutoMapper 从源嵌套集合映射到另一个集合

android - 使用 JFrog Artifactory 的 Kotlin 多平台库

android - 如果 Jetpack Compose 中的文本太长,图标会消失

android - 如何使用 Jetpack 撰写 appbar 后退按钮

android - 在单例私有(private)构造函数类上使用 hilt 进行依赖注入(inject)