Составная видимость не меняется при изменении состояния
У меня есть состояние, и я пытаюсь показатьCircularProgressIndicator
когда значениеtrue
.
@Composable
fun ProductDetailScreen(
viewModel: ProductDetailViewModel = hiltViewModel()
) {
val productState = viewModel.productState.value
LazyColumn{
item {
if (productState.isLoading)
CircularProgressIndicator()
}
}
}
я используюResource
класс для моих результатов вызова API, и в репозитории я использую этот класс для переноса результата моего запроса.
Проблема в том, что я возвращаюсьResource.Loading
из репозитория,isLoading
состояние не обновляется сViewModel
и ProgressIndicator не отображается на моем экране. Что может быть причиной такого поведения?
sealed class Resource<T>(
val data: T? = null,
val message: String? = null,
val errorType: ExceptionMapper.Type? = null
) {
class Success<T>(data: T?) : Resource<T>(data)
class Error<T>(message: String, errorType: ExceptionMapper.Type, data: T? = null) : Resource<T>(data, message, errorType)
class Loading<T>(isLoading: Boolean = true) : Resource<T>()
}
Репозиторий :
override suspend fun getProductComments(productId: Int): Resource<List<Comment>> {
return try {
Resource.Loading<List<Comment>>()
delay(3000)
Resource.Success(apiService.getComments(productId))
} catch (t: Throwable) {
val mappedException = ExceptionMapper.map(t)
Resource.Error(message = t.message!!, errorType = mappedException.type)
}
}
ViewModel:
@HiltViewModel
class ProductDetailViewModel @Inject constructor(
state: SavedStateHandle,
private val productRepository: ProductRepository
) : ViewModel() {
private val passedProduct = state.get<Product>(EXTRA_KEY_DATA)
var productId = passedProduct?.id
var productState = mutableStateOf(ProductState())
private set
init {
getProductComments()
}
private fun getProductComments() {
viewModelScope.launch {
productId?.let { pId ->
when (val commentResult = productRepository.getProductComments(pId)) {
is Resource.Success -> {
commentResult.data?.let { comments ->
productState.value =
productState.value.copy(
comments = comments,
error = null,
isLoading = false
)
}
}
is Resource.Error -> {
productState.value = productState.value.copy(
isLoadFailed = true,
isLoading = false,
error = commentResult.message
)
}
is Resource.Loading -> {
productState.value = productState.value.copy(
isLoadFailed = false,
isLoading = true,
error = null
)
}
}
}
}
}
}
1 ответ
Вы только проверяете это
is Resource.Loading -> {
...
}
когда репозиторий возвращается, в этот момент он бесполезен, потому что при вызовеgetProductComments
сделано, это ужеResource.Success
.
return try {
Resource.Loading<List<Comment>>() // you'll never get this value
delay(3000)
Resource.Success(apiService.getComments(productId))
Поэтому я предлагаю обновитьProductState
перед вызовом репозитория
private fun getProductComments() {
productState.value = productState.value.copy(isLoading = true)
viewModelScope.launch {
...
...
или установитьisLoading
в true как его начальное состояние.
data class ProductState(
...
...
val isLoading : Boolean = true
...
)