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

使用Retrofit+Moshi调用API无响应,Android新闻App求助

问题描述

我正在学习Android开发,尝试搭建一个简易新闻App,但已卡壳3天无法从服务器获取JSON响应。怀疑Retrofit调用存在问题却找不到原因,Logcat中无响应输出(已替换个人API密钥)。

相关代码

private const val BASE_URL = "https://newsapi.org"

private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(BASE_URL)
    .build()

interface CallNewsApi {
    @GET("/v2/top-headlines")
    suspend fun getHeadlines(
        @Query("apiKey") key: String,
        @Query("category") category: String,
        @Query("country") country: String
    ): Response<NewsApiResponse>
}

object NewsApi {
    val retrofitService: CallNewsApi by lazy {
        retrofit.create(CallNewsApi::class.java)
    }
}

data class NewsApiResponse(
    var status: String,
    var totalResults: Int,
    var articles: List<NewsHeadlines>
)

data class NewsHeadlines(
    var source: Source,
    var author: String,
    var title: String,
    var description: String,
    var url: String,
    var urlToImage: String,
    var publishedAt: String,
    var content: String
)

data class Source(
    var id: String,
    var name: String
)

class NewsViewModel : ViewModel() {
    private val _newsList = MutableLiveData<List<NewsHeadlines>>()
    val status: LiveData<List<NewsHeadlines>> = _newsList
    init {
        getNewsLines()
    }
    private fun getNewsLines() {
        viewModelScope.launch {
            try {
                Log.d("ViewModel"," before retrofit")
                val call = NewsApi.retrofitService.getHeadlines(
                    "myApiKey",
                    "sports",
                    "il"
                )
                Log.d("ViewModel", call.body().toString())
            } catch (e: java.lang.Exception) {
                _newsList.value = listOf()
            }
        }
    }
}
问题排查与修复方案

1. 未处理响应状态与错误信息

当前代码仅打印响应体,未检查请求是否成功,也未捕获并打印请求失败的状态码、错误信息及异常栈,导致无法定位问题。修改getNewsLines方法:

private fun getNewsLines() {
    viewModelScope.launch {
        try {
            Log.d("ViewModel"," before retrofit")
            val response = NewsApi.retrofitService.getHeadlines(
                "myApiKey",
                "sports",
                "il"
            )
            if (response.isSuccessful) {
                Log.d("ViewModel", "响应成功: ${response.body().toString()}")
                response.body()?.let {
                    _newsList.value = it.articles
                } ?: Log.e("ViewModel", "响应体为空")
            } else {
                Log.e("ViewModel", "请求失败,状态码: ${response.code()}")
                response.errorBody()?.let {
                    Log.e("ViewModel", "错误详情: ${it.string()}")
                }
            }
        } catch (e: Exception) {
            Log.e("ViewModel", "请求异常", e)
            _newsList.value = listOf()
        }
    }
}

2. 数据类字段未兼容空值

NewsAPI返回的部分字段(如author、source.id、urlToImage)可能为null,当前数据类使用非空类型会导致Moshi解析抛出异常。修改数据类为可空类型:

data class NewsHeadlines(
    var source: Source,
    var author: String?,
    var title: String,
    var description: String?,
    var url: String,
    var urlToImage: String?,
    var publishedAt: String,
    var content: String?
)

data class Source(
    var id: String?,
    var name: String
)

3. 基础配置检查

  • 确认AndroidManifest.xml已添加网络权限:
    <uses-permission android:name="android.permission.INTERNET" />
    
  • 用浏览器/Postman直接访问接口链接(替换真实API密钥),验证接口本身是否能返回有效数据:
    https://newsapi.org/v2/top-headlines?apiKey=你的密钥&category=sports&country=il
  • 检查API密钥有效性:确认密钥未过期、未超出请求次数限制,且允许当前App包名访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 08:40:34