【问题标题】:Unable to invoke no-args constructor for class ConversionRates无法为类 ConversionRates 调用无参数构造函数
【发布时间】:2022-12-05 04:10:28
【问题描述】:

我有一个货币转换器 Android 应用程序。我正在使用改造从 API 获取费率但就我而言,我的应用程序无法从 api 获取数据并返回该异常

无法为类 package name.ConversionRates 调用无参数构造函数。为此类型向 Gson 注册 InstanceCreator 可能会解决此问题。

ConversionRates 数据类:

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>}

【问题讨论】:

    标签: api kotlin gson retrofit data-class


    【解决方案1】:

    显然,kotlin 数据类只能包含大约127 个参数,所以你有两个选择。

    1. 将响应数据类分解为两个(费率ATOL和速率MToZ) 并向 API 发出两个请求。

    2. 将 JSON 对象 (conversion_rates) 转换为对象列表 Rate(val code: String, val amount: Double) .这可以使用 Moshi 自定义适配器来完成。

      在此处查看代码要点Custom Moshi adapter GitHub 上的完整项目fxConverter

      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()
          }
         }
      

    【讨论】:

      【解决方案2】:

      我对此不确定,但是当它说“无法调用无参数构造函数”时,对我来说,这听起来像是您需要能够创建不带参数的 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,
      )
      

      【讨论】:

      • 感谢您的回答,但它没有用。
      猜你喜欢
      • 2015-08-02
      • 2019-10-19
      • 2019-05-07
      • 2020-02-14
      • 2020-06-15
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      相关资源
      最近更新 更多