Android访问Health Connect数据时出现资源未调用close错误求助
Health Connect读取步数时出现“A resource failed to call close.”崩溃的原因分析
问题代码
suspend fun readStepsByTimeRange( healthConnectClient: HealthConnectClient, startTime: Instant, endTime: Instant ) { val response = healthConnectClient.readRecords( ReadRecordsRequest( StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) for (stepRecord in response.records) { // do stuff } }
崩溃堆栈信息
D/StrictMode: StrictMode policy violation: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks. Callsite: close at android.os.StrictMode$AndroidCloseGuardReporter.report(StrictMode.java:1992) at dalvik.system.CloseGuard.warnIfOpen(CloseGuard.java:338) at sun.nio.fs.UnixSecureDirectoryStream.finalize(UnixSecureDirectoryStream.java:580) at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:319) at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:306) at java.lang.Daemons$Daemon.run(Daemons.java:140) at java.lang.Thread.run(Thread.java:1012)
原因分析
这个错误是Android StrictMode检测到可关闭资源未被正确释放导致的,具体原因:
ReadRecordsResponse实现了Closeable接口,它持有Health Connect底层的文件/目录流资源,当前代码使用完response后未调用close()方法释放资源,造成资源泄漏。- 从堆栈信息可见,未关闭的是
UnixSecureDirectoryStream,这是Health Connect存储数据依赖的底层资源,只要ReadRecordsResponse不关闭,这些资源会一直被持有,触发StrictMode的违规检测并导致崩溃。
修复方案
使用Kotlin的use扩展函数自动关闭ReadRecordsResponse,该函数会在代码块执行完成后(无论是否抛出异常)自动调用close():
suspend fun readStepsByTimeRange( healthConnectClient: HealthConnectClient, startTime: Instant, endTime: Instant ) { healthConnectClient.readRecords( ReadRecordsRequest( StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ).use { response -> for (stepRecord in response.records) { // do stuff } } }
内容的提问来源于stack exchange,提问作者Paul Jablonski
相关产品推荐
相关产品推荐

