Handler机制

在这里插入图片描述

Handler机制 是一种进程内部、线程间的通信机制,主要用于异步消息的处理。它涉及多个关键组件,包括Handler、Looper、MessageQueue和Message,共同协作以实现消息的发送、接收和处理。
Handler:负责发送消息和处理消息。当发出一个消息后,首先进入一个消息队列,发送消息的函数即刻返回,而另一个部分在消息队列中逐一将消息取出,然后对消息进行处理。这种机制通常用来处理相对耗时比较长的操作。
Looper:负责循环读取MessageQueue中的消息,读到消息之后就把消息交给Handler去处理。
MessageQueue:存储消息对象的队列。
Message:消息对象,是Handler机制中传递的基本单位。

为什么需要消息机制
Android规定访问UI只能在主线程中进行,在子线程中访问UI就会抛异常。但是Android又不建议在主线程中做耗时操作,导致ANR。所以,我们需要在子线程中做完耗时操作,然后去到主线程更新UI的办法。

Handler的主要作用是将一个任务切换到指定的线程中去执行。

分发机制
Handler通过sendMessage()发送Message到MessageQueue队列;

Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理;

经过dispatchMessage()后,交回给Handler的handleMessage()或者runnable来进行相应地处理。

消息的发送、入队
//消息发送

Handler
在这里插入图片描述

在这里插入图片描述

//入队
MessageQueue为链表结构,发送的消息按照时间加入到链表中
在这里插入图片描述

消息的出队、分发
//取出消息
MessageQueue
在这里插入图片描述

Handler
在这里插入图片描述

同步屏障(syncBarrier)
优先处理异步消息,拦住同步消息队列;
在MessageQueue中postSyncBarrier方法,内部会创建一个没有target(Handler对象)的消息。MessageQueue.next()方法中判断如果target为空且不为同步消息时取出异步消息;
发送异步消息:Message.setAsynchronous设置为异步消息,同时Handler构造方法也可设置。
在这里插入图片描述

关于同步屏障的使用,可了解绘制方法ViewRootImpl的scheduleTraversals。

内存泄露
Activity内使用Handler时,内部类Handler引用Activity对象,当消息未处理完成并关闭页面时,造成Activity对象无法回收造成内存泄漏;

/**
为避免handler造成的内存泄漏
1、使用静态的handler,对外部类不保持对象的引用
2、但Handler需要与Activity通信,所以需要增加一个对Activity的弱引用
*/
private static class MyHandler extends Handler {
private final WeakReference mActivityReference;

MyHandler(Activity activity) {
this.mActivityReference = new WeakReference(activity);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity = (MainActivity) mActivityReference.get(); //获取弱引用队列中的activity
//若引用,判断null
if(activity != null){

}
}

其他考虑问题
1.一个线程有且仅有一个Looper,通过线程的数据存储类ThreadLocal存储,Looper构造函数中会创建MessageQueue。当handler把消息加入到消息队列时,Message内部配置了一个target(即Handler对象),这就可以保证Looper分发消息时对应哪个Handler去处理消息;

2.关于Message:发送的消息通过new Message或者Message.obtain()获得,Message内部维持了一个链表结构的缓存池sPool,sPool的最大容量为50,当消息处理完后recycle放入sPool中,当调用obtain()方法时会从缓冲池中取出消息再次使用,因此使用时最好通过此方法获取消息,可减少内存使用;

3.Handler为什么不会阻塞主线程,因为loop方法无线循环,为什么不会卡死?

真在卡死主线程的操作是某个消息处理时间过长发生ANR,而非循环。没有消息时会阻塞在loop的nativePollOnce方法中,此时主线程会释放CPU资源进入休眠状态,采用linux的ePoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。

4.发送消息post(Runnable)和sendMessage区别
在这里插入图片描述
callback不为空,即post,会把消息交给msg.callback处理。callback为空,即sendMessage,会判断Handler当前的mCallback(构造器传入)是否为空,不为空交给mCallback处理,否则调用Handler重写的handleMessage处理。

5.子线程使用Handler需要手动创建Looper并loop,至于主线程为什么不需要手动创建可自行了解。

6.Android其他实现异步的方式

继承Thread类

HandlerThread

IntentService

AsyncTask

线程池

其他欢迎补充

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值