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

使用Retrofit2切换API后仍报W/System: A resource failed to call close如何解决

Retrofit2 报错问题定位与解决方法

问题复现

修改baseUrl对接其他API后程序报错,修复配置甚至切回原有正常API后仍抛出相同错误,同时附带警告:

W/System: A resource failed to call close.

定位步骤

  • 首先排查缓存残留问题:Android Studio增量编译、APP本地缓存都可能导致旧代码残留,即使改了配置也运行旧逻辑
  • 其次排查接口权限问题:favqs的公开API需要携带授权请求头才能正常调用,未携带头信息会返回401未授权错误
  • 再排查空指针风险:请求失败时response.body()为null,直接调用会触发崩溃
  • 最后排查资源泄漏问题:请求返回错误时,response.errorBody()持有的IO流未主动关闭,会触发资源未关闭的警告

解决方法

1. 清理缓存排除旧代码干扰

  • 卸载测试设备上的对应APP,清除残留数据
  • 执行Android Studio顶部菜单 Build -> Clean Project 再执行 Rebuild Project
  • 重启Android Studio和测试设备后重新运行测试

2. 给请求增加授权头信息

favqs接口需要携带平台分配的API密钥作为请求头才能正常调用,通过OkHttp拦截器统一添加头信息:

// 先构建带请求头的OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .addInterceptor(chain -> {
        Request originalRequest = chain.request();
        Request updatedRequest = originalRequest.newBuilder()
            // 替换为你自己申请的favqs API密钥
            .header("Authorization", "Token token=\"你的API密钥\"")
            .method(originalRequest.method(), originalRequest.body())
            .build();
        return chain.proceed(updatedRequest);
    })
    .build();

// 把okHttpClient设置给Retrofit
Retrofit.Builder builder = new Retrofit.Builder()
    .baseUrl("https://favqs.com/api/")
    .client(okHttpClient) // 新增这行
    .addConverterFactory(GsonConverterFactory.create());

3. 优化响应处理逻辑,增加资源释放

修改onResponse方法,增加非空判断,请求失败时主动关闭errorBody释放资源:

@Override
public void onResponse(Call<Example> call, Response<Example> response) {
    if (response.isSuccessful() && response.body() != null) {
        Example repos = response.body();
        Log.d("mylog1", String.valueOf(repos));
        listView.setAdapter(new MyAdapter(MainActivity.this, repos));
    } else {
        // 主动关闭错误响应的流,避免资源泄漏
        if (response.errorBody() != null) {
            try {
                response.errorBody().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Toast.makeText(MainActivity.this, "请求失败,错误码:" + response.code(), Toast.LENGTH_SHORT).show();
    }
}

4. 页面销毁时主动取消请求

把Call<Example> call改为MainActivity的成员变量,在onDestroy生命周期中主动取消未完成的请求,避免内存泄漏和资源泄漏:

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private Call<Example> call; // 定义为成员变量

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...原有逻辑不变
        call = client.reposForUser(); // 不要局部定义,赋值给成员变量
        // ...原有请求逻辑不变
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 页面销毁时取消未完成的请求
        if (call != null && !call.isCanceled()) {
            call.cancel();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 17:54:04