深入handler源码

直接干!


new一个handler不带参数的时候,callback默认为null(没有回调),async为false(非同步调用)。

看上去是用了一个现成的Looper,将looper里的消息队列赋值到自己的队列,callback一看就知道是有了消息之后的回调,async我们后面再看看具体应用场景




可以看到,他们都是发送的sendMessageDelayed。
然后看看getPostMessage里面干了什么:

将runnable封装成了一个Message对象,但是我们使用handler.send的时候好像没有这一步,只是将Message.what进行了赋值,不妨猜想一下,等执行sendMessage的时候执行的是new Handler对象的callback回调(也就是handleMessage),而执行到post(runnable)的时候执行的Message里的callback(即runnable的run方法)。带着这个疑问继续往下看


见名知意,将Message设置好target(Handler)和async(同步)插入到消息队列MessageQueue中。


那么在这里,首先判断了消息队列是否在退出(折射到线程是否在退出)。
如果不是,先判断Message的when是不是在队列最开始的Message前面(when即Message的延迟执行时间)。是的话就插入到队列最前端,否则插入按照延迟执行的时间插入到队列中。然后根据线程是否blocked来决定是否要唤醒线程。

引申:如果主线程没有消息了,Looper会不断循环是否有消息,会造成CPU的负担吗?
答:到了这里我们可以看到,如果Looper没有消息队列的话,会进入blocked状态,减少CPU的消耗。

那么既然插入到消息队列了,我们都知道是Looper来进行消息的消费,那我们来看看到底是怎么执行的。
那直接看loop方法:


标记1处我们可以看到,通过myLooper方法获取到Looper对象,具体过程为调用ThreadLocal的get方法,用我们的线程做key,获取到线程的ThreadLocalMap对象(线程独有, 不与其他线程共享)即获取到Looper对象,如果为null,就进行初始化,

可以看到,默认初始,化为null,但是这里使用了protected进行方法的修饰,那么我们就可以通过自定义TheadLocal进行默认的Looper对象的初始化,这里以后再进行尝试。

继续回到loop方法中,终于进到for循环了

第一行可以看到,是在进行MessageQueue的遍历,除了圈出来的,其他都是进行系统的log日志填写,而圈出来的方法,则是在进行Message的分发,那我们来看它干了啥

果然如此!验证了上面的猜想,先看Message的callback是否为空,不为空使用Message的callback进行回调(post一个runnable),为空的话就调用handleMessage进行回调(send一个Message)

接下来也没啥重要的了,来看下recycleUncheked干了啥。


这里将next只想sPool(上一个重置属性的Message),然后将sPool指向自己(当前正在使用的Message),回收池数量增加。那么我们可以看到回收池数量有个上限(50个),啥时候才会减少呢?

我们可以明白,是从回收池中获取一个Message(上面recycle使我们知道回收的时候是将除了标记,其他所有属性都抹去了),如此我们可以避免新建一个Message,多增加内存开销。

最后我们来看一下next到底干了什么:



从上往下:

nextPollTimeoutMillis表示距离下一个需要处理的Message的时间,当没有消息时,该值为-1,如果不为0,将Binder里的写操作完成(native),
防止它被阻塞

然后调用nativePollOnce来进行延时唤醒(在这期间如果有其他操作能立即唤醒,也就是nativeWake)

接下来进入第一个循环,也就是设置同步屏障后(Message.target == null)的异步消息,这里在上图已经标明,异步消息需要先执行

当队列中没有消息或者指针指向的消息是一个异步消息的时候,就会执行IdleHandler,之后会将pendingIdleHandlerCount赋值0,也就永远不会执行idleHandler了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值