实现思绪
卡顿监控告急监控:慢方法的监控、ANR的监控、掉帧的监控。实在现方案告急有三种:
- Looper的Printer在消息执行前后的打印,计算出消息执行时间。
- 利用Choreographer向其注册CALL_BACK, 监听Vsync的开始从而得到上一帧的执行时间。
比如对慢方法、ANR的监控,则是对主线程的Looper的消息的监听,对掉帧的监听则是对Choreographer注册CALL_BACK。下面则分段实现卡顿的监控。
Looper的监控
利用Looper的Printer监听消息的开始和竣事,如果对Handler源码这块不认识的发起先看看Handler的源码。
这里要留意的一点是,在设置Printer时即不能覆盖原来的Printer又要查抄本次的Pritner是否被后续的Printer覆盖。
下面的LooperMonitor工具类就是实现Printer的兼容和查抄,同时把变乱通过Listener分发出去
object LooperMonitor { /** * 主线程的Looper */ private var defaultMainLooper = Looper.getMainLooper() private var listeners: MutableList<LooperDispatchListener?> = mutableListOf() private var isReflectLoggingError = false private var printer: LooperPrinter? = null private var isStarted = false private val TAG = "LooperMonitor" private var lastCheckPrinterTime: Long = 0 private const val CHECK_TIME = 60 * 1000L /** * 通过监听去分发的Looper的消息的开始和竣事 * 注册监听,如果有监听则主动给Looper设置Printer */ fun addDispatchListener(listener: LooperDispatchListener?) { listener ?: return if (!listeners.contains(listener)) { listeners.add(listener) } // 如果监听>0 ,则调用 start() 方法 if (listeners.size > 0 && !isStarted) { start() } } /** * 移除监听,没有监听主动竣事对移除Looper的Printer */ fun removeDispatchListener(listener: LooperDispatchListener?) { listener ?: return if (listeners.contains(listener)) { listeners.remove(listener) } // 没有监听主动竣事对移除Looper的Printer if (listeners.size <= 0 && isStarted) { stop() } } private fun start() { isStarted = true // 设置Looper的Printer resetPrinter() // 增长IdleHandler,制止Printer被覆盖 addIdleHandler() } private fun stop() { isStarted = false if (printer != null) { // 移除监听 synchronized(listeners) { listeners.clear() } // Printer设置成原来的Printer defaultMainLooper.setMessageLogging(printer?.origin) removeIdleHandler() defaultMainLooper = null printer = null } } /** * 检测Looper原来是否有Printer,如果有不要将原来的Printer覆盖,然后设置本次的Printer */ private fun resetPrinter() { var originPrinter: Printer? = null try { if (!isReflectLoggingError) { // 通过反射,拿到Lopper的mLogging变量 originPrinter = ReflectUtils.get(defaultMainLooper::class.java, "mLogging", defaultMainLooper) // 检测Printer是否被后续的Printer覆盖 if (originPrinter == printer && printer != null) { return } if (originPrinter != null && printer != null) { if (originPrinter.javaClass.name == printer?.javaClass?.name) { return } } } } catch (e: Exception) { isReflectLoggingError = true e.printStackTrace() } // 设置本次的Printer,并适配原来的Printer printer = LooperPrinter(originPrinter) defaultMainLooper.setMessageLogging(printer) } /** * 在MessageQueue空闲的时间,执行Looper的Printer的查抄,制止被后续的Printer覆盖 */ private fun addIdleHandler() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { defaultMainLooper.queue.addIdleHandler(idleHandler) } else { try { val queue: MessageQueue? = ReflectUtils.get(defaultMainLooper::class.java, "mQueue", defaultMainLooper) queue?.addIdleHandler(idleHandler) } catch (e: Exception) { e.printStackTrace() } } } private fun removeIdleHandler() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { defaultMainLooper.queue.removeIdleHandler(idleHandler) } else { try { val queue: MessageQueue? = ReflectUtils.get(defaultMainLooper::class.java, "mQueue", defaultMainLooper) queue?.removeIdleHandler(idleHandler) } catch (e: Exception) { e.printStackTrace() } } } /** * 每隔60s,检测一下本次的Printer是否被别的Printer覆盖 */ private val idleHandler = MessageQueue.IdleHandler { if (SystemClock.uptimeMillis() - lastCheckPrinterTime > CHECK_TIME) { resetPrinter() lastCheckPrinterTime = SystemClock.uptimeMillis() } true } /** * 新的Printer,要适配原来的已有的Printer */ class LooperPrinter(var origin: Printer?) : Printer { private var isValid = false override fun println(x: String?) { // 给原来的Printer调用 if (origin != null) { origin?.println(x) if (origin == this) { throw RuntimeException("$TAG origin == this") } } // 分发给Listener isValid = x?.getOrNull(0) == '>' || x?.getOrNull(0) == '<' if (isValid) { dispatch(x?.getOrNull(0) == '>', x ?: "") } } } /** * 分发给Listener */ private fun dispatch(isBegin: Boolean, log: String) { synchronized(listeners) { listeners.forEach { it ?: return if (isBegin) { if (!it.isHasDispatchStart) { it.onDispatchStart(log) } } else { if (it.isHasDispatchStart) { it.onDispatchEnd(log) } } } } } /** * 分发的接口 */ abstract class LooperDispatchListener { var isHasDispatchStart = false abstract fun dispatchStart() abstract fun dispatchEnd() fun onDispatchStart(x: String?) { isHasDispatchStart = true dispatchStart() } fun onDispatchEnd(x: String?) { isHasDispatchStart = false dispatchEnd() } }}调用LooperMonitor. addDispatchListener()方法就可以得到
主线程的监控
/** * 主线程的监控 * 即监听Looper中的printer,又监听Choreographer中的input animation traversal * Looper和Choreographer结合计算主线程的:方法耗时和帧耗时 */object UIThreadMonitor { @Volatile var isAlive = false // 是否已经开启监测 // 注册UI线程监控的订阅者聚集 private val observers: HashSet<UIThreadMonitorObserver?> = HashSet<UIThreadMonitorObserver?>() private val TAG = "UIThreadMonitor" /** * Choreographer */ // 注册的三种范例 private const val CALLBACK_INPUT = 0 private const val CALLBACK_ANIMATION = 1 private const val CALLBACK_TRAVERSAL = 2 private val DO_QUEUE_END_ERROR: Long = -100 private val CALLBACK_LAST: Int = CALLBACK_TRAVERSAL private var queueStatus = IntArray(CALLBACK_LAST + 1) // 纪录范例的执行状态 private var callbackExist = BooleanArray(CALLBACK_LAST + 1) // 纪录此范例是否已经添加 private var queueCost = LongArray(CALLBACK_LAST + 1) // 纪录各个范例泯灭的时间 private const val DO_QUEUE_DEFAULT = 0 private const val DO_QUEUE_BEGIN = 1 private const val DO_QUEUE_END = 2 // 主线程的Choreographer实例 private var choreographer: Choreographer? = null // 利用反射获取Choreographer的变量和方法 private var callbackQueueLock: Any? = null private var callbackQueues: Array<Any>? = null private var addTraversalQueue: Method? = null // Traversal范例的注册方法 private var addInputQueue: Method? = null // Input范例的注册方法 private var addAnimationQueue: Method? = null // Animation范例的注册方法 private var vsyncReceiver: Any? = null var frameIntervalNanos: Long = 16666666 private var isVsyncFrame = false // 是否为Vsync信号回调 /** * Looper */ // 纪录Looper的开始和竣事的时间 private var dispatchTimeMs = LongArray(4) // 纪录 Looper分发的消息开始的时间 @Volatile private var token = 0L /*** * 开始监测主线程 */ fun startMonitor() { if (Thread.currentThread() != Looper.getMainLooper().thread) { throw AssertionError("must be init in main thread!") } // 添加主线程的Looper的分发 LooperMonitor.addDispatchListener(looperDispatch) // 初始化并向Choreographer注册Callback initAddCallbackByChoreographer() } /*** * 竣事监测主线程 */ fun stopMonitor() { if (isAlive) { isAlive = false observers.clear() LooperMonitor.removeDispatchListener(looperDispatch) } } /** * 增长订阅者,会主动开始监控 */ fun addObserver(observer: UIThreadMonitorObserver) { if (!isAlive) { startMonitor() } synchronized(observers) { observers.add(observer) } } /** * 删除订阅者,会主动竣事监控 */ fun removeObserver(observer: UIThreadMonitorObserver) { synchronized(observers) { observers.remove(observer) if (observers.size <= 0) { stopMonitor() } } } /** * Looper分发的具体处理惩罚逻辑 */ private val looperDispatch = object : LooperMonitor.LooperDispatchListener() { override fun dispatchStart() { this@UIThreadMonitor.dispatchBegin() } override fun dispatchEnd() { this@UIThreadMonitor.dispatchEnd() } } /** * 初始化并向Choreographer注册Callback */ private fun initAddCallbackByChoreographer() { // 反射获取Choreographer的变量和方法 reflectByChoreographer() if (!isAlive) { this.isAlive = true synchronized(this) { // 初始化三个范例的数组 callbackExist = BooleanArray(CALLBACK_LAST + 1) // 此范例是否已经注册 queueStatus = IntArray(CALLBACK_LAST + 1) // 此范例执行的状态 queueCost = LongArray(CALLBACK_LAST + 1) // 此范例的泯灭时间 // 向Choreographer添加CALLBACK_INPUT范例的Callback addFrameCallback(CALLBACK_INPUT, runnable, true) } } } /** * 反射获取Choreographer的变量和方法 */ private fun reflectByChoreographer() { choreographer = Choreographer.getInstance() frameIntervalNanos = ReflectUtils.reflectObject(choreographer, "mFrameIntervalNanos", frameIntervalNanos) callbackQueueLock = ReflectUtils.reflectObject(choreographer, "mLock", Any()) callbackQueues = ReflectUtils.reflectObject(choreographer, "mCallbackQueues", null) callbackQueues?.let { addInputQueue = ReflectUtils.reflectMethod( it[CALLBACK_INPUT], "addCallbackLocked", Long::class.javaPrimitiveType, Any::class.java, Any::class.java ) addAnimationQueue = ReflectUtils.reflectMethod( it[CALLBACK_ANIMATION], "addCallbackLocked", Long::class.javaPrimitiveType, Any::class.java, Any::class.java ) addTraversalQueue = ReflectUtils.reflectMethod( it[CALLBACK_TRAVERSAL], "addCallbackLocked", Long::class.javaPrimitiveType, Any::class.java, Any::class.java ) } vsyncReceiver = ReflectUtils.reflectObject(choreographer, "mDisplayEventReceiver", null) } /** * 向Choreographer添加CALLBACK */ @Synchronized private fun addFrameCallback(type: Int, callback: Runnable, isAddHeader: Boolean) { // callbackExist判定是否已经参加Runnable if (callbackExist[type]) { return } // 判定是否竣事 if (!isAlive && type == CALLBACK_INPUT) { return } // 利用反射,把对应的CALLBACK添加到链表中 try { callbackQueues?.let { synchronized(it) { var method: Method? = null when (type) { CALLBACK_INPUT -> method = addInputQueue CALLBACK_ANIMATION -> method = addAnimationQueue CALLBACK_TRAVERSAL -> method = addTraversalQueue } if (null != method) { method.invoke( it[type], if (!isAddHeader) SystemClock.uptimeMillis() else -1, callback, null ) callbackExist[type] = true } } } } catch (e: Exception) { Log.e(TAG, e.toString()) } } /** * Choreographer中执行Input CALLBACK的回调 */ private val runnable = object : Runnable { override fun run() { val start = System.nanoTime() try { //isBelongFrame标志位为true,标志已经开始纳入统计 doFrameBegin() // 设置CALLBACK_INPUT范例的queueStatus和queueCost doQueueBegin(CALLBACK_INPUT) // 注册CALLBACK_ANIMATION addFrameCallback( CALLBACK_ANIMATION, { // CALLBACK_ANIMATION执行表现,它前面的CALLBACK_INPUT已经执行完了 // 竣事CALLBACK_INPUT统计,更新queueStatus,queueCost,callbackExist的值 doQueueEnd(CALLBACK_INPUT) // 开始统计CALLBACK_ANIMATION doQueueBegin(CALLBACK_ANIMATION) }, true ) // 注册CALLBACK_TRAVERSAL addFrameCallback( CALLBACK_TRAVERSAL, { // 它执行,表现前面的CALLBACK_ANIMATION已经执行完 doQueueEnd(CALLBACK_ANIMATION) // 开始激励CALLBACK_TRAVERSAL doQueueBegin(CALLBACK_TRAVERSAL) }, true ) } catch (e: Exception) { e.printStackTrace() } } } /** * input CallBack的回调开始 * Frame的开始 */ private fun doFrameBegin() { this.isVsyncFrame = true } /** * TRAVERSAL CallBack的竣事,用Looper的分发的竣事做判定 * Frame的竣事 */ private fun doFrameEnd() { doQueueEnd(CALLBACK_TRAVERSAL) for (i in queueStatus) { if (i != DO_QUEUE_END) { queueCost = DO_QUEUE_END_ERROR throw RuntimeException("UIThreadMonitor happens type[$i] != DO_QUEUE_END") } } queueStatus = IntArray(CALLBACK_LAST + 1) addFrameCallback(CALLBACK_INPUT, runnable, true) } /** * 每种范例的开始 */ private fun doQueueBegin(type: Int) { queueStatus[type] = DO_QUEUE_BEGIN queueCost[type] = System.nanoTime() } /** * 每种范例的竣事 */ private fun doQueueEnd(type: Int) { queueStatus[type] = DO_QUEUE_END queueCost[type] = System.nanoTime() - queueCost[type] synchronized(this) { callbackExist[type] = false } } /** * Looper分发的Message开始 */ private fun dispatchBegin() { // 将开始时间分发给订阅者 token = System.nanoTime() dispatchTimeMs[0] = token dispatchTimeMs[2] = SystemClock.currentThreadTimeMillis() synchronized(observers) { observers.forEach { it ?: return if (!it.isDispatchBegin) { it.dispatchBegin(dispatchTimeMs[0], dispatchTimeMs[2], token) } } } } /** * Looper分发的Message竣事 */ private fun dispatchEnd() { // message开始的时间 val startNS = token var intendedFrameTimeNs = startNS if (isVsyncFrame) { // 如果是isVsyncFrame则调用doFrameEnd()表现末了一个CallBack执行已经竣事 doFrameEnd() // 开始时间用Choreographer纪录的开始时间 intendedFrameTimeNs = getIntendedFrameTimeNs(startNS) } // message竣事的时间 val endNs = System.nanoTime() // 分发给订阅者 synchronized(observers) { observers.forEach { it ?: return if (it.isDispatchBegin) { it.doFrame( ApmUtil.getTopActivityName(), startNS, endNs, isVsyncFrame, intendedFrameTimeNs, queueCost[CALLBACK_INPUT], queueCost[CALLBACK_ANIMATION], queueCost[CALLBACK_TRAVERSAL] ) } } // 纪录竣事的时间 dispatchTimeMs[3] = SystemClock.currentThreadTimeMillis() dispatchTimeMs[1] = System.nanoTime() // 分发给订阅者 synchronized(observers) { observers.forEach { it ?: return if (it.isDispatchBegin) { it.dispatchEnd( dispatchTimeMs[0], dispatchTimeMs[2], dispatchTimeMs[1], dispatchTimeMs[3], token, isVsyncFrame ) } } } isVsyncFrame = false } } /** * 反射获取Choreographer纪录的Frame的开始时间:mTimestampNanos */ private fun getIntendedFrameTimeNs(defaultValue: Long): Long { try { return ReflectUtils.reflectObject<Long>( vsyncReceiver, "mTimestampNanos", defaultValue ) } catch (e: Exception) { e.printStackTrace() Log.e(TAG, e.toString()) } return defaultValue } /** * 主线程监控的订阅者 */ abstract class UIThreadMonitorObserver { var isDispatchBegin = false open fun dispatchBegin(beginNs: Long, cpuBeginNs: Long, token: Long) { isDispatchBegin = true } open fun doFrame( focusedActivity: String?, startNs: Long, endNs: Long, isVsyncFrame: Boolean, intendedFrameTimeNs: Long, inputCostNs: Long, animationCostNs: Long, traversalCostNs: Long ) { } open fun dispatchEnd( beginNs: Long, cpuBeginMs: Long, endNs: Long, cpuEndMs: Long, token: Long, isVsyncFrame: Boolean ) { isDispatchBegin = false } }}卡顿的监控
/** * 卡顿监控,包罗:ANR、慢函数、掉帧 */class BlockPlugin : Plugin { private var mainHandler: Handler? = null private var application: Application? = null private var apmWindowManager: ApmWindowManager? = null /** * 慢方法,耗时凌驾500ms */ var SLOW_TIME_BLOCK = 500 // 界说慢方法的时间 private var slowMethodHandlerThread: HandlerThread? = null private var slowMethodStackCollectHandler: Handler? = null private var slowMethodBlockStackTraceMap = HashMap<String, BlockStackTraceInfo>() private val SLOW_COLLECT_TIME: Long = 500L // 网络堆栈的时间 /** * ANR,耗时凌驾5S */ var ANR_TIME_BLOCK = 5_000 // 界说ANR的时间 private var anrHandlerThread: HandlerThread? = null private var anrStackCollectHandler: Handler? = null private var anrBlockStackTraceMap = HashMap<String, BlockStackTraceInfo>() private val ANR_COLLECT_TIME: Long = 1000L // 网络堆栈的时间 /** * 帧:掉帧、帧率 */ var dropFrameListenerThreshold = 3 // 掉帧上报阀值 private var frameHandlerThread: HandlerThread? = null private var frameStackCollectHandler: Handler? = null private var frameBlockStackTraceMap = HashMap<String, BlockStackTraceInfo>() private var frame_collect_time: Long = 16L // 网络堆栈的时间 private var collectCount = 0 // 帧率 private var sumFrameCost: Long = 0 // 帧数泯灭的总时间 private var lastCost = LongArray(1) // 上一次利用的时间 private var sumFrames: Long = 0 // 总共的帧数 private var lastFrames = LongArray(1) // 上一次掉帧的数量 private var maxFps = 0f // 1s中最大的帧率 /** * 开始 */ override fun start(application: Application?) { val sdkInt = Build.VERSION.SDK_INT if (sdkInt < Build.VERSION_CODES.JELLY_BEAN) { return } this.application = application // 在主线程中执行Runnable开始订阅主线程监控 mainHandler = Handler(Looper.getMainLooper()) mainHandler?.post(runnable) } /** * 竣事 */ override fun stop() { mainHandler?.post { UIThreadMonitor.removeObserver(looperListener) } mainHandler?.removeCallbacksAndMessages(null) apmWindowManager?.dismiss() } /** * 开始的Runnable */ private val runnable = Runnable { try { // 初始化子线程handler,用于网络堆栈 initStackHandler() // 开始主线程监控 UIThreadMonitor.addObserver(looperListener) if (!UIThreadMonitor.isAlive) { UIThreadMonitor.startMonitor() } frame_collect_time = UIThreadMonitor.frameIntervalNanos / Constants.TIME_MILLIS_TO_NANO maxFps = (1000f / frame_collect_time.toFloat()).roundToInt().toFloat() // 初始化表现信息的window apmWindowManager = ApmWindowManager().apply { init(application) show() } } catch (e: Exception) { e.printStackTrace() } } /** * 初始化网络:慢函数、ANR、掉帧的堆栈的子线程Handler */ private fun initStackHandler() { slowMethodHandlerThread = HandlerThread("SlowMethodMonitor") slowMethodHandlerThread?.start() slowMethodStackCollectHandler = Handler(slowMethodHandlerThread!!.looper) anrHandlerThread = HandlerThread("ANRMonitor") anrHandlerThread?.start() anrStackCollectHandler = Handler(anrHandlerThread!!.looper) frameHandlerThread = HandlerThread("FrameMonitor") frameHandlerThread?.start() frameStackCollectHandler = Handler(frameHandlerThread!!.looper) } /** * 主线程监控的订阅者 */ private val looperListener = object : UIThreadMonitor.UIThreadMonitorObserver() { override fun dispatchBegin(beginNs: Long, cpuBeginNs: Long, token: Long) { super.dispatchBegin(beginNs, cpuBeginNs, token) //装炸弹 ,子线程耽误去网络堆栈 slowMethodStackCollectHandler?.postDelayed( slowMethodStackCollectTask, SLOW_COLLECT_TIME ) anrStackCollectHandler?.postDelayed(anrStackCollectTask, ANR_COLLECT_TIME) frameStackCollectHandler?.postDelayed(frameStackCollectTask, frame_collect_time) } override fun dispatchEnd( beginNs: Long, cpuBeginMs: Long, endNs: Long, cpuEndMs: Long, token: Long, isVsyncFrame: Boolean ) { super.dispatchEnd(beginNs, cpuBeginMs, endNs, cpuEndMs, token, isVsyncFrame) // 拆炸弹 slowMethodStackCollectHandler?.removeCallbacks(slowMethodStackCollectTask) anrStackCollectHandler?.removeCallbacks(anrStackCollectTask) val costTime = (endNs - beginNs) / Constants.TIME_MILLIS_TO_NANO // 慢方法 if (costTime >= SLOW_TIME_BLOCK && slowMethodBlockStackTraceMap.isNotEmpty()) { val traceList = slowMethodBlockStackTraceMap.values.toList() traceList.forEach { Log.e(SLOW_METHOD, "慢函数 -> 耗时=${costTime}ms \n ${it.stackTrace}") } // 更新表现到window中 apmWindowManager?.insertSlowMethodCount() } slowMethodBlockStackTraceMap.clear() // ANR if (costTime >= ANR_TIME_BLOCK && anrBlockStackTraceMap.isNotEmpty()) { val traceList = anrBlockStackTraceMap.values.toList() traceList.forEach { Log.e(ANR, "ANR函数-> 耗时=${costTime}ms \n ${it.stackTrace}") } // 更新表现到window中 apmWindowManager?.insertANRCount() } anrBlockStackTraceMap.clear() } override fun doFrame( focusedActivity: String?, startNs: Long, endNs: Long, isVsyncFrame: Boolean, intendedFrameTimeNs: Long, inputCostNs: Long, animationCostNs: Long, traversalCostNs: Long ) { // 拆炸弹 frameStackCollectHandler?.removeCallbacks(frameStackCollectTask) application ?: return // App在前台 if (ApmUtil.isAppRunningInForground(application!!, application!!.packageName)) { // 执行时间 val jitter = endNs - intendedFrameTimeNs // 跳过的帧数 val dropFrame = (jitter / UIThreadMonitor.frameIntervalNanos) if (apmWindowManager?.isShowing == false) { apmWindowManager?.show() } // 跳帧 if (dropFrame > dropFrameListenerThreshold && frameBlockStackTraceMap.isNotEmpty()) { val traceList = frameBlockStackTraceMap.values.toMutableList() val string = StringBuffer() traceList.forEach { string.append(it.stackTrace.toString()) } Log.e(DROP_FRAME, "掉帧函数 = ${dropFrame}次 \n ${string}") // 更新表现到window中 apmWindowManager?.dropFrameCount(dropFrame.toInt()) } frameBlockStackTraceMap.clear() // 帧率 sumFrameCost += ((dropFrame + 1) * frame_collect_time)// 总时间相加 sumFrames += 1 // 总帧数+1 val duration = (sumFrameCost - lastCost[0]).toFloat() // 这次帧数的时间 val collectFrame = sumFrames - lastFrames[0] // 总帧数 - 前次的帧数 if (duration >= 200) { val fps = maxFps.coerceAtMost(1000f * collectFrame / duration) // 更新表现到window中 apmWindowManager?.updateFrameRate(fps.toInt()) lastCost[0] = sumFrameCost // 上一次的时间 即是总时间 lastFrames[0] = sumFrames // 上一次的总帧率 } } else { if (apmWindowManager?.isShowing == true) { apmWindowManager?.dismiss() } } } } /** * 慢函数定时网络堆栈任务 */ private val slowMethodStackCollectTask = object : Runnable { override fun run() { val info = BlockStackTraceInfo(ThreadManager.getJavaStackByName(Looper.getMainLooper().thread.name)) val key = info.getMapKey() val value = slowMethodBlockStackTraceMap[key] if (value == null) { slowMethodBlockStackTraceMap[key] = info } slowMethodStackCollectHandler?.postDelayed(this, SLOW_COLLECT_TIME) } } /** * ANR定时网络堆栈任务 */ private val anrStackCollectTask = object : Runnable { override fun run() { val info = BlockStackTraceInfo(ThreadManager.getJavaStackByName(Looper.getMainLooper().thread.name)) val key = info.getMapKey() val value = anrBlockStackTraceMap[key] if (value == null) { anrBlockStackTraceMap[key] = info } anrStackCollectHandler?.postDelayed(this, SLOW_COLLECT_TIME) } } /** * 掉帧定时网络堆栈任务 */ private val frameStackCollectTask = object : Runnable { override fun run() { collectCount++ if (collectCount > 1) { val info = BlockStackTraceInfo(ThreadManager.getJavaStackByName(Looper.getMainLooper().thread.name)) val key = info.getMapKey() val value = frameBlockStackTraceMap[key] if (value == null) { frameBlockStackTraceMap[key] = info } else { value.collectCount++ } } frameStackCollectHandler?.postDelayed(this, frame_collect_time) } } companion object { const val SLOW_METHOD = "SlowMethod" // 慢方法堆栈的Log const val ANR = "ANR" // ANR堆栈的Log const val DROP_FRAME = "DropFrame" // 掉帧堆栈的Log }} |