Kotlin协程内打印的Logcat日志被吞 如何查看相关日志?
Kotlin协程内部Logcat日志被吞的解决方案
常见触发原因
- 协程执行时抛出未捕获异常,触发协程取消流程,后续日志逻辑未执行
- 协程运行在非主线程的调度器上,Logcat的过滤配置误筛了对应线程的日志
- 全局协程异常处理器拦截了异常后附带关闭了日志输出通道,或者ProGuard/R8混淆时误删了日志调用代码
可落地的解决方法
1. 优先排查协程未捕获异常问题
给协程添加CoroutineExceptionHandler上下文捕获异常,避免协程意外终止导致日志未输出:
// 自定义协程异常处理器 val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> Log.e("CoroutineError", "协程运行异常", throwable) } // 启动协程时传入处理器 viewModelScope.launch(coroutineExceptionHandler + Dispatchers.IO) { Log.d("CoroutineTest", "协程内部日志") // 业务逻辑 }
如果用async启动的协程,需要在调用await()的位置主动捕获异常:
viewModelScope.launch { val deferred = async(Dispatchers.IO) { Log.d("AsyncTest", "async内部日志") // 业务逻辑 } try { deferred.await() } catch (e: Exception) { Log.e("AsyncError", "await捕获异常", e) } }
2. 调整Logcat过滤规则
- 关闭Logcat的
Regex过滤模式,切换为Package过滤,确认选择的应用包名正确 - 把日志级别调到
Verbose,确认没有误筛低级别日志 - 多进程环境下需要在Logcat的进程选择框中选中对应进程
3. 排查混淆/编译配置问题
检查模块下的proguard-rules.pro文件,确认没有添加屏蔽日志的混淆规则,Debug编译模式下可添加规则保留所有日志调用:
-keep class android.util.Log {*;}
另外确认build.gradle中没有开启isDebuggable = false配置,非Debug编译模式下部分ROM会默认屏蔽应用的Verbose、Debug级别日志。
4. 日志打印位置校验
不要把日志打印在finally代码块中紧跟cancel()调用的位置,协程取消后finally中的代码如果没有切换到NonCancellable上下文会直接跳过执行:
// 错误写法,cancel后finally的日志不会打印 viewModelScope.launch { try { // 业务逻辑 } finally { Log.d("Test", "取消后打印的日志") } cancel() } // 正确写法,非可取消上下文保证日志执行 viewModelScope.launch { try { // 业务逻辑 } finally { withContext(NonCancellable) { Log.d("Test", "取消后也能打印的日志") } } cancel() }
内容的提问来源于stack exchange,提问作者ChristianCuevas
相关产品推荐
相关产品推荐

