Android compose composable, ViewModel, List and List Item state
The required dependency for compose ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1"
A simple data object to be displayed in list items. WellnessTask.kt
import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue class WellnessTask( val id: Int, val label: String, initialChecked: Boolean = false ) { var checked: Boolean by mutableStateOf(initialChecked) }
A ViewModel, the state managers that manages the list data. WellnessViewModel.kt
import androidx.compose.runtime.toMutableStateList import androidx.lifecycle.ViewModel class WellnessViewModel : ViewModel() { /** * Don't expose the mutable list of tasks from outside the ViewModel. * Instead define _tasks and tasks. _tasks is internal and mutable inside the ViewModel. * tasks is public and read-only. */ private val _tasks = getWellnessTasks().toMutableStateList() val tasks: Listget() = _tasks fun remove(item: WellnessTask) { _tasks.remove(item) } fun changeTaskChecked(item: WellnessTask, checked: Boolean) = tasks.find { it.id == item.id }?.let { task -> task.checked = checked } } private fun getWellnessTasks() = List(30) { i -> WellnessTask(i, "Task # $i") }
A list item composable view that displays the information from the data object, as well as getting user inputs from the UI. WellnessTaskItem.kt
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.material.Checkbox import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @Composable fun WellnessTaskItem( taskName: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier ) { Row( modifier = modifier, verticalAlignment = Alignment.CenterVertically ) { Text( modifier = Modifier .weight(1f) .padding(start = 16.dp), text = taskName ) Checkbox( checked = checked, onCheckedChange = onCheckedChange ) IconButton(onClick = onClose) { Icon(Icons.Filled.Close, contentDescription = "Close") } } }
The list composable which actually creates the list view with the list data it receives and displays them with the list item composables, it also manages the callbacks received from each list item composable when user taps on the check box or close button, then redirects the callbacks further up to let the parent view handle the events.
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @Composable fun WellnessTasksList( list: List, onCheckedTask: (WellnessTask, Boolean) -> Unit, onCloseTask: (WellnessTask) -> Unit, modifier: Modifier = Modifier ) { LazyColumn( modifier = modifier ) { items( items = list, /** * Use key param to define unique keys representing the items in a mutable list, * instead of using the default key (list position). This prevents unnecessary * recompositions. */ key = { task -> task.id } ) { task -> WellnessTaskItem( taskName = task.label, checked = task.checked, onCheckedChange = { checked -> onCheckedTask(task, checked) }, onClose = { onCloseTask(task) } ) } } }
Finally, the composable that calls the list composable with the data and ViewModel for managing the data. WellnessScreen.kt
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun WellnessScreen( modifier: Modifier = Modifier, wellnessViewModel: WellnessViewModel = viewModel() ) { Column(modifier = modifier) { WellnessTasksList( list = wellnessViewModel.tasks, onCheckedTask = { task, checked -> wellnessViewModel.changeTaskChecked(task, checked) }, onCloseTask = { task -> wellnessViewModel.remove(task) } ) } }
Reference:
https://github.com/googlecodelabs/android-compose-codelabs
Search within Codexpedia
Search the entire web