gson 无法为类ConversionRates调用无参数构造函数

j2qf4p5b  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(190)

我有一个货币转换器Android应用程序。我正在使用retrofit从API获取汇率**,但**就我而言,我的应用程序无法从API获取数据,它返回了该异常
无法调用类package name . ConversionRates得无参数构造函数.使用Gson注册此类型得InstanceCreator可能会解决此问题.

转换率数据类别:

data class ConversionRates(
val AED: Double,
val AFN: Double,
val ALL: Double,
val AMD: Double,
val ANG: Double,
val AOA: Double,
val ARS: Double,
val AUD: Double,
val AWG: Double,
val AZN: Double,
val BAM: Double,
val BBD: Double,
val BDT: Double,
val BGN: Double,
val BHD: Double,
val BIF: Double,
val BMD: Double,
val BND: Double,
val BOB: Double,
val BRL: Double,
val BSD: Double,
val BTN: Double,
val BWP: Double,)

视图模型

@HiltViewModelclass MainViewModel @Inject constructor(
private val repository: MainRepository,
private val dispatchers: DispatcherProvider) : ViewModel(){

sealed class CurrencyEvent {
    class Success(val resultText: String): CurrencyEvent()
    class Failure(val errorText: String): CurrencyEvent()
    object Loading: CurrencyEvent()
    object Empty: CurrencyEvent() }

private val _conversion= MutableStateFlow<CurrencyEvent>(CurrencyEvent.Empty)
val conversion: StateFlow<CurrencyEvent> = _conversion

fun convert(amountStr: String,
    fromCurrency: String,
    toCurrency: String ){

    val fromAmount= amountStr.toFloatOrNull()
    if( fromAmount== null){
        _conversion.value=CurrencyEvent.Failure("Not a valid amount")
        return
    }
    viewModelScope.launch (dispatchers.io){
        _conversion.value= CurrencyEvent.Loading
        when( val ratesResponse= repository.getRates(fromCurrency)) {
            is Resource.Error -> _conversion.value= CurrencyEvent.Failure(ratesResponse.message!!)
            is Resource.Success -> {
                val rates = ratesResponse.data!!.conversion_rates
                val rate = getRateForCurrency(toCurrency, rates)
                if (rate==null){
                    _conversion.value= CurrencyEvent.Failure("Unexpected Error")
                } else {
                    //val convertedCurrency = round(fromAmount * rate * 100)
                    _conversion.value= CurrencyEvent.Success(
                        "$fromAmount $fromCurrency = $toCurrency"
                    )
                }
            }
        }
    }
}
private fun getRateForCurrency(currency: String, rates: ConversionRates) = when (currency) {
    "CAD" -> rates.CAD
    "HKD" -> rates.HKD
    "ISK" -> rates.ISK
    "EUR" -> rates.EUR
    "PHP" -> rates.PHP
    "DKK" -> rates.DKK
    "HUF" -> rates.HUF
    "CZK" -> rates.CZK
    "AUD" -> rates.AUD
    "RON" -> rates.RON
    "SEK" -> rates.SEK
    "IDR" -> rates.IDR
    "INR" -> rates.INR
    "BRL" -> rates.BRL
    "RUB" -> rates.RUB
    "HRK" -> rates.HRK
    "JPY" -> rates.JPY
    "THB" -> rates.THB
    "CHF" -> rates.CHF
    "SGD" -> rates.SGD
    "PLN" -> rates.PLN
    "BGN" -> rates.BGN
    "CNY" -> rates.CNY
    "NOK" -> rates.NOK
    "NZD" -> rates.NZD
    "ZAR" -> rates.ZAR
    "USD" -> rates.USD
    "MXN" -> rates.MXN
    "ILS" -> rates.ILS
    "GBP" -> rates.GBP
    "KRW" -> rates.KRW
    "MYR" -> rates.MYR
    else -> null
}}

货币Api

interface CurrencyApi {

@GET("/v6/68c54e50f924117c29176f8f/latest/USD")
suspend fun getRates(
    @Query("base_code") base_code : String
): Response<CurrencyResponse>}

默认主存储库

class DefaultMainRepository @Inject constructor(
private val api :CurrencyApi): MainRepository {
override suspend fun getRates(base_code: String): Resource<CurrencyResponse> {

    return try {
        val response = api.getRates(base_code)
        val result= response.body()
        if (response.isSuccessful && result!=null){
            Resource.Success(result)
        } else{
            Resource.Error(response.message())
        }
    }catch (e: Exception) {
        Resource.Error(e.message?: "An error occured")
    }
}}

主存储库:

interface MainRepository {

suspend fun getRates(base_code: String) : Resource<CurrencyResponse>}
w6lpcovy

w6lpcovy1#

我不确定这一点,但当它说“无法调用无参数构造函数”时,我觉得这听起来像是你需要能够创建一个没有参数的CurrencyResponse示例。也许可以尝试设置一些默认值?我会给予一下:

data class ConversionRates(
    val AED: Double = 0.0,
    val AFN: Double = 0.0,
    val ALL: Double = 0.0,
    val AMD: Double = 0.0,
    val ANG: Double = 0.0,
    val AOA: Double = 0.0,
    val ARS: Double = 0.0,
    val AUD: Double = 0.0,
    val AWG: Double = 0.0,
    val AZN: Double = 0.0,
    val BAM: Double = 0.0,
    val BBD: Double = 0.0,
    val BDT: Double = 0.0,
    val BGN: Double = 0.0,
    val BHD: Double = 0.0,
    val BIF: Double = 0.0,
    val BMD: Double = 0.0,
    val BND: Double = 0.0,
    val BOB: Double = 0.0,
    val BRL: Double = 0.0,
    val BSD: Double = 0.0,
    val BTN: Double = 0.0,
    val BWP: Double = 0.0,
)
n3schb8v

n3schb8v2#

看起来,Kotlin数据类只能包含大约127个参数,所以你有两个选择。
1.将响应数据类分解为两个(RatesAToLRatesMToZ),并向API发出两个请求。
1.将JSON对象(conversion_rates)转换为对象列表Rate(val code: String, val amount: Double)。这可以通过使用莫希自定义适配器来完成。
请参阅此处的代码要点Custom Moshi adapter

class MoshiJsonAdapter : JsonAdapter<InfoAndRatesResponse>() {

    @FromJson
    override fun fromJson(reader: JsonReader): InfoAndRatesResponse {

    reader.beginObject()

    var result = ""
    var timeLastUpdateUnix = 0
    var timeLastUpdateUtc = ""
    var timeNextUpdateUnix = 0
    var timeNextUpdateUtc = ""
    var baseCode = ""
    val rates = mutableListOf<Rate>()

    while (reader.hasNext()) {
        when (reader.nextName()) {
            "result" -> result = reader.nextString()
            "time_last_update_unix" -> timeLastUpdateUnix = reader.nextInt()
            "time_last_update_utc" -> timeLastUpdateUtc = reader.nextString()
            "time_next_update_unix" -> timeNextUpdateUnix = reader.nextInt()
            "time_next_update_utc" -> timeNextUpdateUtc = reader.nextString()
            "base_code" -> baseCode = reader.nextString()
            "conversion_rates" -> {

                reader.beginObject()

                while (reader.peek() != JsonReader.Token.END_OBJECT) {

                    val code = reader.nextName()

                    val amount = when (code) {
                        baseCode -> reader.nextInt().toDouble()
                        else -> reader.nextDouble()
                    }

                    val infoBaseCode = baseCode

                    Timber.tag("MyTag")
                        .d(" code $code amount $amount infoBaseCode $infoBaseCode")

                    rates.add(
                        Rate(
                            code = code,
                            amount = amount,
                            infoBaseCode = infoBaseCode,
                        )
                    )
                }
                reader.endObject()
            }
            else -> reader.skipValue()
        }
    }
    reader.endObject()

    return InfoAndRatesResponse(
        result = result,
        timeLastUpdateUnix = timeLastUpdateUnix,
        timeLastUpdateUtc = timeLastUpdateUtc,
        timeNextUpdateUnix = timeNextUpdateUnix,
        timeNextUpdateUtc = timeNextUpdateUtc,
        baseCode = baseCode,
        rates = rates
     )
    }

   @ToJson
    override fun toJson(writer: JsonWriter, value: 
    InfoAndRatesResponse?) {
    throw UnsupportedOperationException()
    }
   }

相关问题