正确理解Handler机制

正确姿势理解Handler机制

Handler机制的组成元素:Looper对象、Handler对象、线程

  • 线程通过Looper.prepare()方法设置当前线程绑定一个Looper对象
  • 紧接着创建一个Handler对象,Handler类会默认设置好Looper对象、MessageQueue,如果在创建Handler对象之前没有调用prepare()方法,就会抛出异常结束程序
  • 到此才算是做好了准备工作,值得一提的是主线程会在入口main方法里自动做好准备工作并且还会设置主线程绑定的Looper为主Looper,而一般的线程都是没有默认绑定的Looper对象和默认创建的Handler对象的,详细请自行查阅源码。
  • 如果希望尽快理解Handler机制,建议直接理解HandlerThread和Handler的使用,那样你会明白子线程想要轮询消息的时候会分几步做。

Handler机制的原理:消息的发送、传递、处理

消息的发送:

  • 通过Handler的sendMessage()发送出去,实际情况却是会通过之前绑定的MessageQueue调用enqueueMessage()并把消息作为参数传入

消息的传递:

  • MessageQueue通过调用enqueueMessage()将消息入队之后,然后又因为Looper对象负责MessageQueue的出队,通过调用loop()不断尝试从消息队列中获取消息,直到队列为空。注意了,当队列为空时就是一个死循环。因而此时线程阻塞,同样也是loop(),这个时候由于消息队列不为空取出消息后,会调用dispatchMessage()会回调Handler对象的handleMessage()方法,这个时候便进入了handler对象所在的线程了。
  • 但是问题来了,为什么线程阻塞还能sendMessage()?这一点我放在后面解释。

消息的处理:

  • 通常在重写handlerMessage()方法利用switch分支实现不同消息对应的不同代码块。

 

线程阻塞与sendMessage()

  • 线程阻塞了是因为loop()对吧,loop()出现在哪里?
  • 如果你去查阅一下源码,你会发现,主线程的loop()调用出现在main方法的最后,这意味着什么,当主线程所有操作结束之后才会轮到loop()的死循环,而sendMessage()会将消息入队,loop()获取到不为空的消息后进行一系列分发处理。那么有人问了,线程阻塞了为什么还能调用sendMessage,不应该让出CPU吗?那么你就得了解一下死循环和阻塞了。

死循环VS阻塞

  • 死循环会占据cpu,不会被android系统判定为阻塞从而迫使让出cpu的。
  • 或者说,真正意义上的阻塞是诸如Wait()、suspend()等这类方法的调用造成的线程阻塞。
  • 详情可看以下链接,是一名远古时代的csdn博客作者将一些帖子贴出来的,其中对死循环和阻塞有争论。加油!
  • https://blog.csdn.net/zhhxidian2005/article/details/1636695

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值