I have a ViewModel class:
class ItemsModel : ViewModel() {
private val _tasks = MutableStateFlow<List<TaskItem>>(listOf())
val tasks = _tasks.asStateFlow()
fun onTaskDone(index: Int) {
_tasks.value = _tasks.value.toMutableList().apply {
get(index).task.done = !get(index).task.done
}
}
fun onTaskRemove(index: Int) {
val listSize = _tasks.value.size
_tasks.value = _tasks.value.toMutableList().apply {
if (index < listSize)
removeAt(index)
}
}
fun addTask(task: String) {
_tasks.value = _tasks.value.toMutableList().apply {
add(TaskItem(this.size + 1, Task(task)))
}
}
}
The data class of TaskItem
:
@Parcelize
data class TaskItem(var index: Int, var task: Task) : Parcelable
The data class of Task
:
@Parcelize
data class Task(var task: String = "", var done: Boolean = false) : Parcelable
In the target composable screen I call that like this:
...
val itemsModel: ItemsModel = viewModel()
val tasks by itemsModel.tasks.collectAsState()
...
Whenever I call this itemsModel.onTaskDone(index)
the LazyColumn
doesn't get updated until another changes are made to the list, e.g. adding new task item into the list.
So far I understand, that change doesn't take place on LazyColumn
since I change a value within the Object Task
that is a variable within TaskItem
. If I had a String
instead of Task
the changes could appear immediately, don't they?
Anyway, I need to get changes shown in LazyColumn
. How can I solve this?
I foun a solution if someone should be still loocking for.
I jst defined a new SnapshotStateList
variable within screen:
var tasks = remember { mutableStateListOf<Task>() }
It allows changing data within the list and recompose LazyColumn
like this:
val item = tasks[index]
tasks[index] = item.copy(done = !tasks[index].done)
For more info please also check this question and answer.
Please make sure that you also set a key for LazyColumn
:
itemsIndexed(tasks, key = { _, task -> task.hashCode() }) { index, task -> /* Your code */ }