Android使用Loopj调用GitHub API获取用户信息报错及接口问题
解决GitHub API获取用户name/followers字段的问题
我一眼就看出问题所在啦——你调用的https://api.github.com/users是用户列表接口,它返回的是用户的精简信息集合,只包含login、avatar_url这类基础字段,根本没有name、followers、following这些详细数据!要拿到这些字段,必须对每个用户单独调用详情接口:https://api.github.com/users/{login}(把{login}替换成用户的登录名)。
结合你用的Loopj库,我帮你修改了代码,思路是:先获取用户列表拿到每个用户的login,再逐个请求详情接口补全数据,最后统一更新RecyclerView。
修改后的完整代码
private fun getDataGitDetail() { progressBar.visibility = View.VISIBLE val client = AsyncHttpClient() client.addHeader("Authorization", "token 6fe9dff2e5e43d25eb3abe9ff508a750b972f725") client.addHeader("User-Agent", "request") val url = "https://api.github.com/users" client.get(url, object : AsyncHttpResponseHandler() { override fun onSuccess(statusCode: Int, headers: Array<Header>, responseBody: ByteArray) { progressBar.visibility = View.INVISIBLE val result = String(responseBody) Log.d(TAG, result) try { val jsonArray = JSONArray(result) // 计数已完成的详情请求,避免异步请求未结束就更新列表 var completedRequests = 0 val totalUsers = jsonArray.length() for (i in 0 until jsonArray.length()) { val userListItem = jsonArray.getJSONObject(i) val login = userListItem.getString("login") val avatarUrl = userListItem.getString("avatar_url") // 调用单个用户详情接口 val detailUrl = "https://api.github.com/users/$login" client.get(detailUrl, object : AsyncHttpResponseHandler() { override fun onSuccess( detailStatusCode: Int, detailHeaders: Array<Header>, detailResponseBody: ByteArray ) { val detailResult = String(detailResponseBody) val detailJsonObject = JSONObject(detailResult) // 从详情接口提取所需字段,用opt系列方法避免字段不存在报错 val name = detailJsonObject.optString("name") val company = detailJsonObject.optString("company") val location = detailJsonObject.optString("location") val followers = detailJsonObject.optInt("followers") val following = detailJsonObject.optInt("following") val repositoryCount = detailJsonObject.optInt("public_repos") // 添加到数据列表,name为空时用login兜底 listData.add( Data( login, name.takeIf { it.isNotEmpty() } ?: login, avatarUrl, company, location, repositoryCount, followers, following ) ) // 所有请求完成后更新列表 completedRequests++ if (completedRequests == totalUsers) { showRecyclerList() } } override fun onFailure( detailStatusCode: Int, detailHeaders: Array<Header>?, detailResponseBody: ByteArray?, error: Throwable ) { // 单个用户请求失败的容错处理,跳过该用户或用默认值 Log.e(TAG, "Failed to fetch details for $login", error) completedRequests++ if (completedRequests == totalUsers) { showRecyclerList() } } }) } } catch (e: Exception) { Toast.makeText(this@MainActivity, e.message, Toast.LENGTH_SHORT).show() e.printStackTrace() } } override fun onFailure( statusCode: Int, headers: Array<Header>, responseBody: ByteArray, error: Throwable ) { progressBar.visibility = View.INVISIBLE val errorMessage = when (statusCode) { 401 -> "$statusCode : Unauthorized" 403 -> "$statusCode : Forbidden" 404 -> "$statusCode : Not Found" else -> "$statusCode : ${error.message}" } Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show() } }) }
关键修改点说明
- 接口切换逻辑:先通过列表接口拿到
login,再用login拼接详情接口URL获取完整用户数据 - 异步请求同步处理:用计数器确保所有详情请求完成后再更新RecyclerView,避免列表显示不全
- 安全取值:用
optString()/optInt()替代getString()/getInt(),防止部分用户未填写字段时抛出异常 - 容错机制:单个用户详情请求失败时,仍会推进计数并最终更新列表,避免整个流程卡住
内容的提问来源于stack exchange,提问作者Just Lovanto
相关产品推荐
相关产品推荐

