Составная видимость не меняется при изменении состояния

У меня есть состояние, и я пытаюсь показать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
     ...
)
Другие вопросы по тегам