没有合适的资源?快使用搜索试试~ 我知道了~
首页Android打印主线程所有方法执行时间
前言: 我们知道Android卡顿主要是主线程中有耗时操作导致的,那么我们怎么能方便快捷的获取主线程中的所有耗时方法执行时间呢?今天我们来介绍两个方案 方案一:利用Looper.java中loop()方法的logging.print的特殊关键字进行耗时打印: 在消息分发时,主线程的looper.loop()方法会遍历所有的消息进行分发,执行耗时任务。我们看下源码的loop()方法: for (;;) { Message msg = queue.next(); // might block if (msg == null) {
资源详情
资源评论
资源推荐

Android打印主线程所有方法执行时间打印主线程所有方法执行时间
前言:前言:
我们知道Android卡顿主要是主线程中有耗时操作导致的,那么我们怎么能方便快捷的获取主线程中的所有耗时方法执行时间呢?今天我们来介绍两个方案
方案一:利用方案一:利用Looper.java中中loop()方法的方法的logging.print的特殊关键字进行耗时打印:的特殊关键字进行耗时打印:
在消息分发时,主线程的looper.loop()方法会遍历所有的消息进行分发,执行耗时任务。我们看下源码的loop()方法:
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
... ...
... ...
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
可以发现,每个消息在分发开始和执行结束后,在logging.print()方法里有 >>>>> 和和 <<<<<< 的特殊字符,那么我们可以根据这个特殊字符来作为这个消息执行的开始和结束标志,
进而依此来打印主线程中的消息执行时间,具体代码如下:
/**
* 方案一:只能打印耗时消息,无法知道具体是哪个消息耗时
*/
private void methodOne() {
outputMainLooper();
}
private void outputMainLooper() {
Looper.getMainLooper().setMessageLogging(new Printer() {
@Override
public void println(String x) {
if (x.startsWith(">>>>>")) {
startTime = System.currentTimeMillis();
} else if (x.startsWith("<<<< 10) {
Log.i("buder mainLoop ------ :", (end - startTime)+ " ");
}
}
}
});
}
这种方案能简单快速打印出主线程中消息的具体执行时间,但是我们的目的是要找出具体哪个方法耗时,需要打印出耗时方法的堆栈信息才能帮助我们快速定位到卡顿点。因此方案
一仅打印message的耗时时间而无法定位到具体函数,局限性较大,没有多大意义。
方案二:利用方案二:利用Handler.java的的sendMessageAtTime()、、dispatchMessage()方法,找出耗时函数并打印耗时时间:方法,找出耗时函数并打印耗时时间:
我们知道主线程中发送消息,最终会调用sendMessageAtTime方法入消息队列,然后通过dispatchMessage进行消息分发执行。那么我们分别利用这两个方法就可以监控到消息是谁
发的,以及这个消息的执行时间。为了能够做到这些,我们利用epic框架对这两个函数进行hook,具体做法如下:
步骤一:步骤一:gradle中添加库依赖:中添加库依赖:
implementation 'me.weishu:epic:0.6.0'
步骤二:步骤二:hook sendMessageAtTime 和和 dispatchMessage
/**
* 方案二:可以打印耗时消息以及耗时时间
*/
private void methodTwo() {
final long[] startTime = {0};
//hook sendMessageAtTime,具体msg消息是谁
DexposedBridge.findAndHookMethod(Handler.class, "sendMessageAtTime", Message.class, long.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
sMsgDetail.put((Message) param.args[0], Log.getStackTraceString(new Throwable()).replace("java.lang.Throwable", ""));
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});
//hook dispatchMessage,打印耗时时间
DexposedBridge.findAndHookMethod(Handler.class, "dispatchMessage", Message.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
startTime[0] = System.currentTimeMillis();
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);

















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0