使用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
相关产品推荐
相关产品推荐

