You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Retrofit请求API无法打印MutableLiveData数据问题

问题描述

Kotlin开发初学者在Android开发学习过程中遇到以下问题:已在应用清单文件中添加网络权限,但调用API接口后无法打印任何返回数据,尝试输出MutableLiveData中承载的接口数据时未得到预期结果,相关实现代码如下:

ApiServices

interface ApiServices {
@GET("/fixer/latest/")
fun getRatesData(
    @Query("base") base: String,
    @Query("apikey") apikey: String
): Call<CurrencyModel>

companion object {
    private const val url = "https://api.apilayer.com/"
    var apiServices: ApiServices? = null

    fun getInstance(): ApiServices {
        if (apiServices == null) {
            val retrofit = Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
            apiServices = retrofit.create(ApiServices::class.java)
        }
        return apiServices!!
    }
 }
}

Repository

class CurrencyRepository constructor(private val apiServices: ApiServices) {
    fun getLatestRates() = apiServices.getRatesData("EUR", "API_KEY");
}

ViewModel

class CurrencyViewModel constructor(private val currencyRepository: CurrencyRepository) :
ViewModel() {
val currencyRatesList = MutableLiveData<CurrencyModel>()
val errorMessage = MutableLiveData<String>()

fun getLatestRates() {
    val response = currencyRepository.getLatestRates();
    response.enqueue(object : retrofit2.Callback<CurrencyModel> {
        override fun onResponse(
            call: retrofit2.Call<CurrencyModel>,
            response: Response<CurrencyModel>
        ) {
            currencyRatesList.postValue(response.body())
        }

        override fun onFailure(call: retrofit2.Call<CurrencyModel>, t: Throwable) {
            errorMessage.postValue(t.message)
        }
    })
}
}

FactoryViewModel

class CurrencyViewModelFactory constructor(private val repository: CurrencyRepository) :
ViewModelProvider.Factory {

override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    return if (modelClass.isAssignableFrom(CurrencyViewModel::class.java)) {
        CurrencyViewModel(this.repository) as T
    }else{
        throw IllegalArgumentException("Couldn't found ViewModel")
    }
 }
}

MainActivity

class MainActivity : AppCompatActivity() {

private val retrofitService = ApiServices.getInstance()
lateinit var viewModel: CurrencyViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
        .get(CurrencyViewModel::class.java)
    viewModel.currencyRatesList.observe(this, Observer {
        Log.d(TAG, "onCreate: $it")
    })
    viewModel.errorMessage.observe(this, Observer {
        viewModel.getLatestRates()
    })
 }
}
问题根因
  • 核心逻辑遗漏:Activity中注册完LiveData观察者后,从未主动调用viewModel.getLatestRates()触发接口请求。现有逻辑只有errorMessage收到错误回调时才会触发请求,应用首次启动时根本不会发起网络调用,自然不会有返回数据。
  • 错误回调逻辑异常:errorMessage的观察者中直接递归调用getLatestRates(),一旦请求触发错误会无限循环发起重试,直接导致请求队列阻塞。
  • 响应校验缺失:Retrofit的onResponse回调仅代表拿到了HTTP响应,不代表请求成功。现有逻辑未判断response.isSuccessful状态,也未处理响应体为null的情况,遇到4xx/5xx错误时不会走onFailure回调,会直接向LiveData投递null值。
  • 路径写法不规范:baseUrl已配置为带尾斜杠的根路径,@GET注解的路径开头额外加了/,后续如果调整baseUrl增加子路径,会出现路径拼接错误。
修复步骤
  1. 在MainActivity的onCreate方法中,观察者注册完成后主动触发首次接口请求:
// 放在两个observe调用之后
viewModel.getLatestRates()
  1. 修正错误观察者逻辑,移除递归重试代码,先打印错误信息定位问题,重试逻辑建议绑定到手动点击事件上,不要自动递归调用:
viewModel.errorMessage.observe(this, Observer { errorMsg ->
    Log.e(TAG, "接口请求失败: $errorMsg")
})
  1. 补全ViewModel中的响应状态校验,区分成功/失败响应:
override fun onResponse(
    call: retrofit2.Call<CurrencyModel>,
    response: Response<CurrencyModel>
) {
    if (response.isSuccessful && response.body() != null) {
        currencyRatesList.postValue(response.body())
    } else {
        errorMessage.postValue("请求异常,状态码:${response.code()}")
    }
}
  1. 修正ApiServices的接口路径,去掉@GET路径开头的冗余斜杠:
@GET("fixer/latest/")
fun getRatesData(
    @Query("base") base: String,
    @Query("apikey") apikey: String
): Call<CurrencyModel>

额外注意:代码中的API_KEY需要替换为你在apilayer平台申请的真实有效密钥,否则会返回401权限错误。

内容的提问来源于stack exchange,提问作者asdwq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:57:24