Skip to content

Instantly share code, notes, and snippets.

@fishyer
Last active August 1, 2019 10:58
Show Gist options
  • Save fishyer/3156d74f8e9dd2d15f034ad2e189cb81 to your computer and use it in GitHub Desktop.
Save fishyer/3156d74f8e9dd2d15f034ad2e189cb81 to your computer and use it in GitHub Desktop.
package com.daigou.sg.helper
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.util.Log
/**
* 开启一个异步线程,每过一段时间(比如100ms)就去获取主线程的栈帧
* 如果当前栈帧和上一个栈帧一样,就说明主线程阻塞了,就打印当前的栈帧
* 注意:需要过滤掉系统的阻塞方法
* Author:Yutianran on 2019-08-01 16:57
*/
object BlockDetectUtil {
private val TIME_BLOCK = 100L//阈值
private val whiteList = mutableListOf<String>().apply {
add("android.os.MessageQueue.nativePollOnce")
add("ThreadedRenderer.nSyncAndDrawFrame")
}
private val ioHandler: Handler by lazy {
val handlerThread = HandlerThread("BlockDetectUtil")
handlerThread.start()
return@lazy Handler(handlerThread.looper)
}
@JvmStatic
fun init() {
ioHandler.post(ioRunnable)
}
private val ioRunnable = object : Runnable {
var last = ""
override fun run() {
val stackTraceString = getMainThreadStackTrace()
if (checkBlock(stackTraceString)) {
Log.e("BlockDetectUtil", "当前方法耗时超过${TIME_BLOCK}ms:\n $stackTraceString")
}
last = stackTraceString
ioHandler.postDelayed(this, TIME_BLOCK)
}
private fun getMainThreadStackTrace(): String {
val sb = StringBuilder()
val stackTrace = Looper.getMainLooper().thread.stackTrace
for (s in stackTrace) {
sb.append(s.toString() + "\n")
}
return sb.toString()
}
private fun checkBlock(stackTraceString: String): Boolean {
whiteList.forEach {
if (stackTraceString.contains(it)) {
return false
}
}
if (last == stackTraceString) {
return true
}
return false
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment