In classic Android programming (before composites) to show list on recyclerview I need adapter and if I want to give any action like clickable element, where logic will be provide in fragment/viewmodel I had to through argument create such parameter like
(Int) -> Unit
how does it look in jetpack compose when I create lazy column? Should it look the same and just create paramaters in Screens/UI
then configure logic in the same way in fragment/viewmodel or there is some other approachs?
Getting rid of all the bloat of recyclerview is one of my favorite advantages of compose. Let's assume you'd like to include the following list in your screen:
@Composable
private fun TestList(
myItems: List<String>,
onClick: (String) -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumn(modifier.fillMaxSize()) {
items(myItems) { item ->
TestItemView(
text = item,
onClick = onClick
)
}
}
}
@Composable
private fun TestItemView(
text: String,
onClick: (String) -> Unit,
modifier: Modifier = Modifier,
) {
Surface(modifier.fillMaxWidth()) {
Button(
onClick = { onClick(text) },
content = { Text(text) }
)
}
}
Option A: keep the state in the composable.
@Composable
private fun TestScreenA() {
val myItems = remember { mutableStateOf(listOf("A", "B", "C", "D")) }
TestList(
myItems = myItems.value,
onClick = { clickedItem ->
// for demonstration purposes we remove item on click
myItems.value = myItems.value.filterNot { it == clickedItem }
}
)
}
Option B: Keep the state in the viewmodel (like before)
class TestViewModelB: ViewModel() {
private val _myItems = MutableStateFlow(listOf("A", "B", "C", "D"))
val myItems = _myItems.asStateFlow()
fun onItemClicked(clickedItem: String){
// for demonstration purposes we remove item on click
_myItems.update { items -> items.filterNot { it == clickedItem } }
}
}
@Composable
private fun TestScreenB(
// inject viewModel here using your favorite DI-Framework
viewModel: TestViewModelB
) {
TestList(
// you might want to use collectAsStateWithLifecycle in the future
// see https://medium.com/androiddevelopers/consuming-flows-safely-in-jetpack-compose-cde014d0d5a3
myItems = viewModel.myItems.collectAsState().value,
onClick = viewModel::onItemClicked
)
}
Both options are viable (especially when using rememberSavable
).
However, i suggest to use optionB for people just migrating to compose, as its more similar to what they're used. I personally use OptionA for simple states, and OptionB for more complex ones (like a list)