【问题标题】:java.lang.RuntimeException: Failed to invoke public android.arch.lifecycle.LiveData() with no argsjava.lang.RuntimeException:无法调用没有参数的公共 android.arch.lifecycle.LiveData()
【发布时间】:2018-08-23 03:17:49
【问题描述】:

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

java.lang.RuntimeException: 无法调用没有参数的公共 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
}

  }

感谢您的帮助!

【问题讨论】:

  • 也许这不是问题,你能告诉我们改造的 API 接口吗?
  • 我已经更新了帖子
  • Call&lt;LiveData&lt;ForecastResult&gt;&gt; 你有合适的转换器吗?
  • 你用过Repository吗?你也有数据库吗?有你的项目样本给我看吗?请

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


【解决方案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 类中使用 livedata。

【讨论】:

    【解决方案2】:

    是的,因此您的 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 更有意义。


    对这些建议持保留态度,我不完全了解您的应用程序的用例,并且这些规则有例外情况

    【讨论】:

    • 谢谢,问题出在为包装响应和异常而创建的资源类中
    • 谢谢你,Mahmoud Moustafa,我有同样的问题,原因在同一个地方! ;)
    • @mahmoud moustafa 太棒了,这可以帮助您,不要忘记根据 SO 指南投票+接受答案。 :)
    【解决方案3】:

    我使用LiveDataAdapterCall 转换为LiveData,这样您就不需要将Retrofit 响应包装为Call&lt;LiveData&lt;T&gt;&gt;。 这个适配器类似于 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做了一个视频

    【讨论】:

      猜你喜欢
      • 2013-02-26
      • 1970-01-01
      • 2020-11-07
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 2019-07-28
      相关资源
      最近更新 更多