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

使用okhttp3的peekBody()获取响应后,后续代码无法执行的问题

OkHttp响应处理异常排查:第一条Log正常输出,第二条不执行

问题代码

@Override
public void onResponse(Call call, final okhttp3.Response response) throws IOException {
    String res = response.peekBody(99999L).string();
    //String res = response.body().string();
    Log.d("shalocmo", "okhttp3:" + res);
    Log.d("shalocmo", "okhttp3: here");
}

核心排查点与解决方案

  • 隐藏Error导致线程终止:
    你的方法仅声明抛出IOException,但如果读取响应时触发OutOfMemoryError(比如响应内容接近100KB且当前内存不足),这类Error不属于Exception范畴,不会被捕获,会直接终止当前后台线程——这就会出现第一条Log正常输出、后续代码完全不执行的情况。
    验证方法:给代码套上try-finally块,强制执行后续逻辑:

    @Override
    public void onResponse(Call call, final okhttp3.Response response) throws IOException {
        try {
            String res = response.peekBody(99999L).string();
            Log.d("shalocmo", "okhttp3:" + res);
        } finally {
            Log.d("shalocmo", "okhttp3: here");
        }
    }
    

    如果finally里的Log能输出,说明确实是try块内触发了未被捕获的Error。

  • 内存不足导致线程被系统回收:
    你看到的E/memtrack: Couldn't load memtrack module日志,本质是系统内存紧张时内存追踪模块加载失败的提示——这意味着当前设备/模拟器内存不足,OkHttp的后台线程优先级较低,很可能在第一条Log输出后被系统强制回收。
    解决措施:

    • 调小peekBody的字节限制,避免一次性读取过大响应占用内存;
    • 模拟器用户直接调大模拟器分配的内存;真机用户清理后台应用释放内存;
    • 改用自定义高优先级线程池处理响应逻辑,降低被系统回收的概率。
  • Log过滤规则误判:
    虽然第一条Log能输出,但仍需确认Logcat过滤规则:比如是否意外设置了只显示特定进程、或者将日志级别设为高于Debug(Log.d属于Debug级别,若过滤级别设为Info及以上则会被隐藏)。可以临时把第二条Log改成Log.e(Error级别)测试是否能输出。

补充建议

在Application类中注册全局未捕获异常处理器,捕获所有未处理的Error和Exception,便于定位隐藏问题:

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
            Log.e("UncaughtError", "Thread: " + thread.getName(), throwable);
        });
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:50:23