2024年HarmonyOS鸿蒙最新Matrix卡顿优化之IdleHandlerLagTracer源码分析,2024年最新腾讯技术岗面试笔试题

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

前言

IdleHandler是Android系统为开发者提供的一种在消息队列空闲时运行任务的机制,通过IdleHandler执行的任务优先级低于主线程优先级,会在主线程任务执行完成后再执行,所以适用于一些实时性要求不高的任务,通常用于Android启动优化中,将一些优先级较低的任务延后执行,以提高应用启动速度。看下消息队列中的源码。

@UnsupportedAppUsage
Message next() {
//前边省略了很多代码,只有消息队列当前没有需要执行的任务时,才会执行到下边的代码
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
keep = idler.queueIdle();
}
}

那么既然IdleHandler是用于进行性能优化的,为什么matrix还要对其进行监控呢?从上边的分析我们可以知道,IdleHandler也是在主线程消息队列中运行的,所以假如IdleHandler中出现了耗时任务执行,那么很明显就会导致主线程卡顿,IdleHandler也是属于主线程卡顿监控的关键一环。

了解了IdleHandler监控的必要性,我们现在开始今天的源码分析。和其他类型的tracer一致,IdleHandler也是在TracePlugin中进行初始化和调用的,那么我们就从这几个关键方法入手:

  • 构造方法
  • onStartTrace
  • onStopTrace

构造方法

构造方法仅仅是拿到了传入的配置,配置中包含的是IdleHandler监控是否启用的开关,isIdleHandlerTraceEnable。

public IdleHandlerLagTracer(TraceConfig config) {
traceConfig = config;
}

onStartTrace

onStartTrace会调用到onAlive方法,我们看onAlive的源码,首先初始化了一个HandlerThread,然后创建了一个IdleHandlerLagRunnable,最后调用了detectIdleHandler开启监控。

@Override
public void onAlive() {
super.onAlive();
if (traceConfig.isIdleHandlerTraceEnable()) {
//异步线程
idleHandlerLagHandlerThread = new HandlerThread(“IdleHandlerLagThread”);
//上报信息用的runnable
idleHandlerLagRunnable = new IdleHandlerLagRunable();
detectIdleHandler();
}
}

IdleHandlerLagRunnable是用于上报信息的,我们先看detectIdleHandler方法。首先拿到主线程消息队列对象,然后通过反射从MessageQueue对象上获取到mIdleHandlers的Field对象,mIdleHandlers是一个List集合,内部存储了所有当前消息队列添加的IdleHandler对象。拿到之后构造了一个自定义的List-MyArrayList,反射将其设置到消息队列上,这里的目的是将mIdleHandlers作为一个hook点,完成替换之后,主线程添加和移除IdleHandler的操作都在我们的监控范围之内了。

private static void detectIdleHandler() {
MessageQueue mainQueue = Looper.getMainLooper().getQueue();
Field field = MessageQueue.class.getDeclaredField(“mIdleHandlers”);
field.setAccessible(true);
MyArrayList<MessageQueue.IdleHandler> myIdleHandlerArrayList = new MyArrayList<>();
//反射替换消息队列中的List
field.set(mainQueue, myIdleHandlerArrayList);
idleHandlerLagHandlerThread.start();
idleHandlerLagHandler = new Handler(idleHandlerLagHandlerThread.getLooper());
}

MyArrayList

看下MyArrayList的实现。它继承自ArrayList,重写了add和remove方法,也就是拦截了IdleHandler的添加和移除。当通过调用MessageQueue的addIdleHandler方法向list中添加时,就会走到MyArrayList的add方法中,此时会将IdleHandler再包装一层MyIdleHandler存入,达到拦截IdleHandler的queueIdle方法调用的目的。

static class MyArrayList extends ArrayList {
Map<MessageQueue.IdleHandler, MyIdleHandler> map = new HashMap<>();
@Override
public boolean add(Object o) {
if (o instanceof MessageQueue.IdleHandler) {
//包装一层,作为代理。拦截queueIdle方法的执行
MyIdleHandler myIdleHandler = new MyIdleHandler((MessageQueue.IdleHandler) o);
//记录映射关系
map.put((MessageQueue.IdleHandler) o, myIdleHandler);
return super.add(myIdleHandler);
}
return super.add(o);
}
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof MyIdleHandler) {
MessageQueue.IdleHandler idleHandler = ((MyIdleHandler) o).idleHandler;
map.remove(idleHandler);
return super.remove(o);
} else {
MyIdleHandler myIdleHandler = map.remove(o);
if (myIdleHandler != null) {
return super.remove(myIdleHandler);
}
return super.remove(o);
}
}
}

MyIdleHandler

接下来我们看看MyIdleHandler是怎么实现的。可以看到它继承自IdleHandler,并重写了它的queueIdle方法,这样一来每一个IdleHandler执行时都会走到MyIdleHandler的queueIdle方法中,也就都在我们的监控之内了。

static class MyIdleHandler implements MessageQueue.IdleHandler {
@Override
public boolean queueIdle() {
//发送延时消息,延时内未执行完成就上报

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值