Handler原理及源码深入理解

1、handler是什么?

它是android给我们提供用来更新UI的机制,也是一套消息处理机制,我们可以发送消息,也可以处理消息。
拓展:

看ForamWork层源码可以知道

Activity 里的生命周期方法回掉,也是通过handler发送消息,然后通过不同的msg做不同的分支处理。

ActivityThread是应用程序的核心的类,整个应用程序都是通过它创造,包括Activity,以及各种生命周期方法的回调。

里面会有一个默认创建main线程, 所有更新UI的线程都是根据这个main线程创建的

ActivityThread 就是通过Handler机制接受到AMS发送的Activity生命周期的执行管理, 然后进行相关操作

2、为什么要用handler?

正常来说,是不应该再主线程中进行网络请求和UI操作的,这些操作往往耗费大量时间,也会造成主线程的阻塞。

还有可能会造成界面错乱、性能下降等

所以Android设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制就没有办法更新UI,

就会抛出异常信息。也就是不能在非UI线程进行更新UI

3、Handler怎么用?以及与Looper和Messagequeue的关系

先知道一点,1个线程中只能对应1个Looper实例,并且每一个主线程有一个threadLocal对象,它是用来关联Looper对象的。

handler机制如果想运行起来,必须的有Looper对象和messagequeue对象,那为什么在主线程new hanlder()会运行此机制,

点击ActivityThread源码的main方法里,系统会调用Looper.prepareMainLooper();去帮我们创建Looper对象,并且把这个

Looper对象保存到了threadLocal中,并且在Looper的构造方法里创建了Messagequeue对象。然后也会调用Looper.loop();

让这套机制开始工作,如果没有消息就阻塞,如果有的话,从消息队列里取消息,处理消息。这个方法一旦开启之后,

则会自动进入消息循环,这是一个隐式操作。

再点击handler构造方法可以知道,里面会执行Looper.myLooper(); 在点击进去看到这个方法会执行 threadLocal.get()方法

取出之前在threadLocal储存的Looper变量,然后获取到Looper对象,然后通过Looper对象调用它的成员变量mQueue可获取

到Messagequeue对象,这样它们三者就建立了关联。这样就可以运行hanlder消息处理机制了。

如果是在子线程:

子线程中是不会默认没有创建Looper对象,如果想让一个handler在一个子线程中生效,并且执行它的机制,就必须有Looper对象

与它关联,需要先调用Looper.prepare()创建并启用Looper。调用Looper.loop()开启循环抽取消息。

也可以handlerThread来开启子线程,因为它帮你封装了Looper对象,不需要再手动创建。并且开启了消息循环处理机制,

而Thread则不行。handlerThread解决了同步问题,它一次只接收处理一个任务。它还会提升这个子线程的优先级,

保证了在主线程调用handlerThread的hanlder对象,不会报空指针。

接下来看看handler发送消息的流程:

handler发送消息,其实就是向Messagequeue发送message,然后用Looper不断的从Messagequeue提取消息,

并且把消息回传给handler自己。至于如何回传给自己,点击跟进查看即可

详细说明:handler.sendMessage(消息);一直跟进会进入enqueueMessage()方法 ,会有 msg.target = this;

将当前创建的handler对象赋值给这个属性,然后调用queue.enqueueMessage(msg, uptimeMillis); 这个方法的作用是

入队,把每个消息及每个消息发来的时间放入消息队列中。其通过发送的时间,再根据链表的存储结构特点,把时间较短的

移动的链表的头部。

然后一直在执行的Looper.loop()方法,这里面会找到Looper对象和Messagequeue消息队列

然后会有无条件for循环取出数据,如果取出的数据不为null,则会走 Message msg = queue.next(); 如果没有消息就阻塞,

如果有消息,则取出链头的msg消息,并且移除它。然后会走(target)Handler对象调用dispatchMessage(msg)方法,

然后此方法中会判断mag.CallBack函数的返回值,若msg.callback属性不为空,则代表使用了post(Runnable r)发送消息

即回调Runnable对象里复写的run()方法,否则调用Handler自己的 handleMessage(msg);

这样就接收到了,达到了自己发给自己的效果

4、handler用法之截获

如果用handler发送消息,然后接受消息,在以下的情况是可以截获消息的,

@SuppressLint(“HandlerLeak”)
Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {

        会先执行这里面的代码

        return false;  
    }
}){
    @Override
    public void handleMessage(Message msg) {
		
	上面如果返回false,则会执行这个方法里的代码

	上面如果返回true,则不会执行这个方法,会被上面拦截了

        super.handleMessage(msg);
    }
};

5、handlerThread的叙述
handlerThread设计方面比较高效快捷,它帮你把任务的发送,处理都封装了起来,包括帮你封装了

Looper对象,不需要再手动创建。而Thread则不行。

handlerThread解决了同步问题,在主线程创建此类并且获取子线程的hanlder对象,不会报空指针。

因为源码里帮这个线程提升了优先级。

6、更新UI的四种方式

(1) handler.sendmessage(msg);

(2) runOnUiThread(new Runable());

(3) handler.post(new Runable());

(4) mTv.post(new Runable(){mTv.setText(“更新内容”)});

哪有什么岁月静好,只不过有人替你负重前行.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值