Reputation: 317
Im learning Jetpack Compose and Kotlin, what I need to do is populate a lazyrow with some info from an api, but it seems that Im doing something wrong, since the interface is created and a white screen is shown, in the log I can see that API is called and the response is the object I needed, but the lazyrow never gets recomposed again so the white screen stays like that.
This is my code
@Composable
fun ParentHomeComposable(
parentSkills: List<ParentHomeResponseModel>,
){
LazyRow{
items(
items = parentSkills,
key = { parentSkills ->
parentSkills.studentId
}
) { parentSkills ->
ParentItemComposable(
ParentItem = parentSkills,
)
}
}
}
@Composable
fun ParentItemComposable(
ParentItem: ParentHomeResponseModel,
) {
BoxWithConstraints() {
Box() {
Column{
Box()
{
Text(
text = ParentItem.username,
color = DARK_GRAY,
fontWeight = FontWeight.Bold,
overflow = TextOverflow.Ellipsis,
maxLines = 2,
style = MaterialTheme.typography.h4,
textAlign = TextAlign.Center,
)
}
}
}
}
}
this is my viewmodel
@HiltViewModel
class ParentHomeViewModel @Inject
constructor(
private val getParentHomeUseCase: GetParentHomeUseCase,
) : ViewModel() {
private val _uiState = MutableStateFlow(ParentHomeUiState())
val uiState: StateFlow<ParentHomeUiState> = _uiState.asStateFlow()
init {
onGetParentHome()
}
private fun onGetParentHome() {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
val parentHomeResponse = getParentHomeUseCase.getParentHome()
val parentHomeModel = parentHomeResponse.successOr(listOf())
_uiState.update { parentHomeUiState ->
parentHomeUiState.copy(
parentHome = parentHomeModel,
isLoading = false
)
}
}
}
}
my parenthomeUiState
data class ParentHomeUiState(
val parentHome: List<ParentHomeResponseModel> = listOf(),
val isLoading: Boolean = false,
val isDone: Boolean = false
)
this is the log response
{
"avatar": "TACO",
"username": "fdsfss",
"hodStreak": [false, false, false, false, false],
"hodPoints": 0,
"hodRanking": 0,
"hodTopicsViewed": 15,
"studentId": "630d786c25430056356c632c",
"weekProgress": 25,
"generalProgress": 50,
},
{
"avatar": "MICHAELL",
"username": "sffgsf",
"hodStreak": [false, false, false, false, false],
"hodPoints": 0,
"hodRanking": 0,
"hodTopicsViewed": 15,
"studentId": "630d901a25430056356c6460",
"weekProgress": 25,
"generalProgress": 50,
},
my response model
@Parcelize
data class ParentHomeResponseModel(
val avatar: String = "",
val username: String = "",
val hodStreak: List<Boolean>,
val hodPoints: Int = 0,
val hodRanking: Int = 0,
val hodTopicsViewed: Int = 0,
val studentId: String = "",
val weekProgress: Int = 0,
val generalProgress: Int = 0,
val exploredTopics:List<ExploredTopics> ,
): Parcelable{}
any ideas? I thought this was really easy but its not working for me
Upvotes: 0
Views: 453
Reputation: 13129
I will guess a little based on information on your code
ParentHomeComposable(...)
takes a list of type List<ParentHomeResponseModel>
The problem is that this composable is rendered at first time you compose it (let's say on activity / navigation / fragment start, or when your open this composable with setContent) and without any state that the composable needs to know about it will never change, it will be rendered once.
Now I'm assuming that your are listening to the data inside your activity/fragment like this
viewModel.uiState.collect { yourData ->
ParentHomeComposable(yourData.parentHome)
}
but instead you should be doing
@Composable
fun ParentHomeComposable(
parentSkills: List<ParentHomeResponseModel>,
){
val uiState = viewModel.uiState.observeAsState()
LazyRow{
items(
items = uiState.parentHome,
key = { parentSkills ->
parentSkills.studentId
}
) { parentSkills ->
ParentItemComposable(
ParentItem = parentSkills,
)
}
}
}
This code will provide a state to the LazyRow
.
So, when the viewmodel
provides a new uiState
, it will be collected inside the composable and recompose based on the new data.
For more information take a look here
https://developer.android.com/jetpack/compose/architecture
You will get a richer information here
https://developer.android.com/jetpack/compose/lifecycle
Upvotes: 1