StrictMode的DiskReadViolation对measureTimeMillis{}块结果高估及告警咨询
解决StrictMode DiskReadViolation导致measureTimeMillis计时高估的问题
嘿,这个问题我之前也碰到过,来给你拆解一下原因和解决办法:
为什么会出现计时高估?
当StrictMode检测到DiskReadViolation(主线程磁盘读取违规)时,它会触发一系列额外操作:比如遍历调用栈、生成警告日志、执行违规策略(比如弹窗或崩溃)。这些操作本身是有耗时的,而measureTimeMillis{}会把整个代码块里的所有执行时间都算进去——包括StrictMode的检测逻辑耗时,所以你看到的计时结果会比你业务代码的实际耗时高很多。
两种解决思路
1. 临时禁用StrictMode以获得精准计时
如果你只是想精准测量业务代码的耗时,可以在计时过程中临时关闭StrictMode的磁盘读取检测,测量完成后再恢复原有策略:
// 保存当前线程的StrictMode策略 val originalPolicy = StrictMode.getThreadPolicy() try { // 临时允许主线程磁盘读取,关闭相关检测 StrictMode.setThreadPolicy( StrictMode.ThreadPolicy.Builder(originalPolicy) .permitDiskReads() .build() ) // 执行并测量你的业务代码 val actualDuration = measureTimeMillis { // 这里放你要测量的代码,比如调用getFilesDir()等可能触发磁盘读取的操作 val filesDir = context.filesDir // ...其他业务逻辑 } Log.d("PerformanceLog", "业务代码实际耗时: $actualDuration ms") } finally { // 必须恢复原来的StrictMode策略,避免影响后续检测 StrictMode.setThreadPolicy(originalPolicy) }
2. 从根源解决StrictMode违规(推荐)
StrictMode的警告本身是在提醒你:主线程不应该执行磁盘IO操作——这会导致UI卡顿,影响用户体验。所以更彻底的解决办法是把磁盘相关操作移到后台线程:
比如用Kotlin协程的IO调度器:
// 在Android中,结合生命周期使用协程(比如在Activity/Fragment里) lifecycleScope.launch(Dispatchers.IO) { // 在后台线程执行磁盘操作,不会触发StrictMode警告 val duration = measureTimeMillis { val filesDir = context.filesDir // ...其他磁盘读取/写入操作 } // 如果需要更新UI,切回主线程 withContext(Dispatchers.Main) { Log.d("PerformanceLog", "后台磁盘操作耗时: $duration ms") // 更新UI逻辑... } }
这样既解决了StrictMode的违规问题,又能获得准确的计时结果——因为后台线程的StrictMode检测默认是宽松的,不会额外消耗计时时间。
补充说明
如果你只是想调试StrictMode的违规点,不需要精准计时,那直接看警告里的调用栈就可以了——它会告诉你哪一行代码触发了磁盘读取,针对性地把那部分逻辑移到后台即可。
内容的提问来源于stack exchange,提问作者Artem Garkusha
相关产品推荐
相关产品推荐

