java.lang.RuntimeException:无法调用没有args的公共android.arch.lifecycle.LiveData()

时间:2018-03-14 14:30:24

标签: android kotlin gson retrofit android-architecture-components

我正在尝试使用Retrofit和Android架构组件调用API,但我收到此错误

  

java.lang.RuntimeException:无法调用没有args的公共android.arch.lifecycle.LiveData()

这是响应的数据类

data class ForecastResult(val city: City, val list: List<Forecast>)

服务接口

interface ServicesApis { // using dummy data
@GET("data/2.5/forecast/")
fun getForecast(@Query("APPID") APPID: String = "xxxxxxxx"
                , @Query("q") q: String = "94043", @Query("mode") mode: String = "json", @Query("units") units: String = "metric"
                , @Query("cnt") cnt: String = "7"): Call<LiveData<ForecastResult>>
}

和api实现

class WeatherRepoImpl : WeatherRepo {
override fun getDailyForecast(): LiveData<Resource<ForecastResult>> {
    val forecast: MutableLiveData<Resource<ForecastResult>> = MutableLiveData()
    RestAPI.getAPIsrevice().getForecast().enqueue(object : Callback<LiveData<ForecastResult>> {
        override fun onResponse(call: Call<LiveData<ForecastResult>>?, response: Response<LiveData<ForecastResult>>?) {
            when {
                response!!.isSuccessful -> {
                    forecast.postValue(Resource.success(response.body()?.value))
                }
                else -> {
                    val exception = AppException(responseBody = response.errorBody())
                    forecast.postValue(Resource.error(exception))
                }
            }
        }

        override fun onFailure(call: Call<LiveData<ForecastResult>>?, t: Throwable?) {
            val exception = AppException(t)
            forecast.postValue(Resource.error(exception))
        }

    })
    return forecast
}

  }

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

从API调用中删除LiveData并创建ViewModel对象中包含的MutableLiveData类。

例如:

API调用定义如下: (删除LiveData)

   @GET("data/2.5/forecast/")
fun getForecast(@Query("APPID") APPID: String = "xxxxxxxx"
                , @Query("q") q: String = "94043", @Query("mode") mode: String = "json", @Query("units") units: String = "metric"
                , @Query("cnt") cnt: String = "7"): Call<ForecastResult>

创建一个ViewModel类:

class YourViewModel: ViewModel() {

    var allObjLiveData = MutableLiveData<YOUROBJECT>()

    fun methodForAPICall(){

        mApiService?.getForecast(.....)?.enqueue(object : Callback<YOUROBJECT>
        {
            override fun onFailure(call: Call<YOUROBJECT>, t: Throwable) {
                allObjLiveData.value = null
            }

            override fun onResponse(call: Call<YOUROBJECT>, response: Response<YOUROBJECT>) {
                allObjLiveData.value=response.body() //Set your Object to live Data
            }

        })
    }
}

现在在您的活动或片段初始化ViewModel类中。 并观察实时数据。

    yourViewModelClassObj?.allObjLiveData?.observe(this, Observer {
       //whenever object change this method call every time.
      }
    })

因此您可以在ViewModel类中使用实时数据。

答案 1 :(得分:0)

是的,可能您的API响应未正确序列化。

无论如何,将LiveData包装到API响应中是没有意义的。只需像你这样暴露对象:

someLivedataObject: LiveData<YourApiResponseModel> 

// So whenever the APIs response comes in:
someLivedataObject.postValue(YourApiResponseModel)

如果由于某种原因无法使用

someLivedataObject.setValue(YourApiResponseModel)

您可以在文档中详细了解这些内容之间的区别,请注意我正在调用LiveData#setValue()方法,不要使用Kotlin的deference setter方法。

由于您的视图正在观察对已公开的someLivedataObject的更改,因此UI已更新。

这类似于RxJava对应物,其中使用Observable包装器的API响应实际上没有意义,它不是连续的数据流,因此使用Single更有意义。

这些建议含糊不清,我不是完全了解你的应用程序的用例这些规则有例外

答案 2 :(得分:0)

我使用LiveDataAdapterCall转换为LiveData,这样您就不需要将您的Retrofit响应包装为Call<LiveData<T>>。 此适配器类似于Jake的Rx适配器。

here获取LiveDataAdapterFactoryLiveDataAdapter

添加适配器后,您需要进行设置:

Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create(gson))
        .addCallAdapterFactory(LiveDataCallAdapterFactory())
        .baseUrl(BASE_URL)
        .client(httpClient)
        .build()

自我推广:我已经在https://caster.io/lessons/android-architecture-components-livedata-with-retrofit

制作了相同的视频