Retrofit传入完整URL请求时回调始终触发onFailure问题排查
Retrofit请求无报错始终触发onFailure回调修复方案
问题复现
对接BrainShop聊天接口时,Retrofit异步请求始终进入onFailure分支,仅展示预设失败提示,Logcat无明显相关错误日志。
涉及原有代码:
MainActivity核心逻辑:
val url:String="http://api.brainshop.ai/get?bid=167083&key=jIpZgrpRgALYSZ72&uid=[uid]&msg="+message val BASE_URL="http://api.brainshop.ai/" val retrofit=Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() val retrofitAPI=retrofit.create(RetrofitAPI::class.java) val call:retrofit2.Call<MsgModal> = retrofitAPI.getMessage(url) call.enqueue(object: Callback<MsgModal>{ override fun onResponse(call: retrofit2.Call<MsgModal>, response: Response<MsgModal>) { val modal: MsgModal = response.body()!! Toast.makeText(applicationContext,"bsh", Toast.LENGTH_SHORT).show() messageModalArrayList.plusAssign(ChatsModal(modal.cnt, BOT_KEY)) Toast.makeText(applicationContext, modal.cnt, Toast.LENGTH_SHORT).show() chatRVAdapter.notifyDataSetChanged() } override fun onFailure(call: retrofit2.Call<MsgModal>, t: Throwable) { messageModalArrayList.add(ChatsModal("please revert your question",BOT_KEY)) chatRVAdapter.notifyDataSetChanged() } })
MsgModal类定义:
class MsgModal ( var cnt: String )
RetrofitAPI接口定义:
interface RetrofitAPI { @GET fun getMessage(@Url url: String ): Call<MsgModal> }
根因定位与修复
1. 优先修复:明文HTTP请求被系统拦截(90%以上同问题的诱因)
Android 9.0(API 28)及以上版本默认禁止应用发起未加密的HTTP明文请求,现有代码中接口地址使用http://前缀,请求会被系统直接拦截,且多数机型不会针对这类拦截打印显眼的错误日志。
两种修复方案二选一即可,优先选第一种:
- 方案一(推荐):直接将接口地址替换为HTTPS协议,修改两行地址定义:
// 替换原HTTP地址为HTTPS val url:String="https://api.brainshop.ai/get?bid=167083&key=jIpZgrpRgALYSZ72&uid=[uid]&msg="+message val BASE_URL="https://api.brainshop.ai/"
- 方案二(仅在接口不支持HTTPS时使用):配置网络安全规则放开明文权限
- 在
app/src/main/res/xml目录下新建network_security_config.xml文件:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">api.brainshop.ai</domain> </domain-config> </network-security-config>- 在
AndroidManifest.xml中添加配置引用,同时确认已声明网络权限:
<!-- 网络权限声明,放在<application>标签外 --> <uses-permission android:name="android.permission.INTERNET" /> <application android:networkSecurityConfig="@xml/network_security_config" <!-- 其余原有属性不变 --> > <!-- 其余原有组件声明不变 --> </application> - 在
2. 补充错误日志打印,避免无日志无法定位问题
现有onFailure回调未打印异常堆栈,是看不到具体报错的直接原因,先加一行堆栈打印,后续所有请求异常都可以直接在Logcat看到具体原因:
override fun onFailure(call: retrofit2.Call<MsgModal>, t: Throwable) { // 打印异常堆栈 t.printStackTrace() messageModalArrayList.add(ChatsModal("please revert your question",BOT_KEY)) chatRVAdapter.notifyDataSetChanged() }
3. 修正MsgModal定义,避免Gson解析失败
普通Kotlin类没有默认无参构造,Gson在反序列化时可能出现解析失败,将其改为data类即可:
data class MsgModal( val cnt: String )
4. 优化Retrofit接口写法,避免手动拼接URL出错
现有手动拼接全路径URL的写法容易出现转义、格式错误,改用Retrofit注解自动拼接参数更稳定:
interface RetrofitAPI { @GET("get") fun getMessage( @Query("bid") bid: String = "167083", @Query("key") key: String = "jIpZgrpRgALYSZ72", @Query("uid") uid: String, @Query("msg") msg: String ): Call<MsgModal> }
调用时无需手动拼接URL,直接传入参数即可:
// 替换原手动拼接URL的调用方式 val call: Call<MsgModal> = retrofitAPI.getMessage(uid = "替换为实际用户id", msg = message)
验证方式
完成上述修改后重新安装运行应用,若仍进入失败分支,直接查看Logcat中printStackTrace()输出的异常信息,对应调整即可;正常情况下请求会进入onResponse回调,成功获取机器人返回消息并展示在列表中。
内容的提问来源于stack exchange,提问作者Jerina Stanis
相关产品推荐
相关产品推荐

