androidapikotlinandroid-jetpack-composeindexoutofboundsexception

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 Error in Kotlin


I am trying to build an currency exhanger app using an API. When I try to get the first currency, i get indexOutOfBounds Exception. I know that exchangeDetails Array empty is and i cannot reach to an empty array. But i dont know how to fix it.

This is CalculateView

Column {
                    if(calculateViewModel.loading){
                        CircularProgressIndicator()
                    }else{
                        Text(text = calculateViewModel.exchangeDetail[0].get("EUR").toString())
                        Text(text = calculateViewModel.exchangeDetail[0].get(currency2).toString())
                    }

                }

and this is CalculateViewModel

class CalculateViewModel: ViewModel() {

    private val exchangeService = ExchangeService()
    var loading: Boolean by mutableStateOf(false)
    var errorMessage : String by mutableStateOf("")
    var exchangeDetail : MutableList<Map<String, Float>> by mutableStateOf(mutableListOf())

    fun getExchangeRatio(input1: String, input2: String) = viewModelScope.launch {
        errorMessage = ""
        loading = true
        try {
            val ratio = exchangeService.getExchangeCourse(input1,input2)
            exchangeDetail.add(ratio.data)
        }catch (e: Exception){
            errorMessage = e.message.toString()
        }finally {
            loading = false
        }
    }

}

exhchangeDto class

@kotlinx.serialization.Serializable
data class ExchangeDto (

    val data: Map<String, Float>

    //Zugriff über .get()
)

APIManager


class APIManager {
    private val apiKey = "Om1xoJkPAxk9neFbFvzezQtxAuNHdSERTfN8CPbk"
    var jsonHttpClient = HttpClient {
        expectSuccess = true
        install(ContentNegotiation) {
            json(Json {
                ignoreUnknownKeys = true
            })
        }
        defaultRequest {
            url.host = "api.freecurrencyapi.com"
            url.protocol = URLProtocol.HTTPS
            url.encodedPath = "/v1/latest?apikey=$apiKey" + url.encodedPath
            contentType(ContentType.Application.Json)
            headers {
                append(HttpHeaders.Authorization,
                    "Bearer $apiKey")
            }

        }

        HttpResponseValidator {
            getCustomResponseValidator(this)
        }

    }
}

Thanks...

I tried to get the currency value from an array list, i was expecting to call it via get() function. I got IndexOutOfBounds error.


Solution

  • There is several ways to avoid error here.

    One way could be to use the firstOrNull method instead of accessing it using [0]

    Example

    if(calculateViewModel.loading){
                            CircularProgressIndicator()
                        }else{
                            Text(text = calculateViewModel.exchangeDetail.firstOrNull()?.get("EUR")?.toString() ?: "")
                            Text(text = calculateViewModel.exchangeDetail.firstOrNull()?.get(currency2)?.toString() ?: "")
                        }
    
    

    Note that with this " fix " you need to have a default value (empty string here). You can change it for whatever you like.

    One other way could be to check if the array is empty or not before trying to print those texts.

    Example

    
    if(calculateViewModel.loading){
            CircularProgressIndicator()
        }else{
            if(calculateViewModel.exchangeDetail.isNotEmpty()) {
                Text(text = calculateViewModel.exchangeDetail[0].get("EUR").toString())
                Text(text = calculateViewModel.exchangeDetail[0].get(currency2).toString())
            } else {
                // print whatever you want ...
            }
        }