参考转载地址:图解Handler机制
参考地址:Android Handler 机制(二):Handler 机制深入探究问题梳理
Handler
是一套消息处理机制,是Android SDK来处理异步消息的核心类
Handler
用于子线程与主线程通信。子线程可以通过Handler
来通知主线程进行UI更新
参考地址:Android之Handler用法总结
Android Developers 地址:http://www.android-doc.com/reference/android/os/Handler.html
构造方法 | 用途 |
---|---|
Handler() | 使得该handler与当前线程的Loop相关联 |
Handler(Handler.Callback callback) | 使得该handler与当前线程的Loop相关联,且在回调接口中可以处理message |
Handler(Looper looper) | 使得该handler与自定义的Loop相关联 |
Handler(Looper looper,Handler.Callback callback) | 使得该handler与自定义的Loop相关联,且在回调接口中可以处理message |
返回值 | 公共方法 | 用途 |
---|---|---|
void | dispatchMessage(Message msg) | 处理系统消息 |
final void | dump(Printer pw, String prefix) | 打印出Handler和Looper对象的信息,包含Looper中的Message个数等 |
String | getMessageName(Message message) | 返回表示指定消息名称的字符串 |
void | handleMessage(Message msg) | 发送消息和接收消息 |
final boolean | hasMessages(int what, Object object) | 检查消息队列中是否有包含what属性且Object为指定值的消息 |
final boolean | hasMessages(int what) | 检查消息队列中是否有包含what属性为指定值的消息 |
final Message | obtainMessage(int what, int arg1, int arg2) | 从Handler获取Message |
final Message | obtainMessage() | 从Handler获取Message |
final Message | obtainMessage(int what, int arg1, int arg2, Object obj) | 从Handler获取Message |
final Message | obtainMessage(int what) | 从Handler获取Message |
final Message | obtainMessage(int what, Object obj) | 从Handler获取Message |
final boolean | post(Runnable r) | 在Handler所在线程,创建一个封装Runnable的Message对象 |
final boolean | postAtFrontOfQueue(Runnable r) | 立即发送封装Runnable的Message到队列,而且是放在队列的最前面 |
final boolean | postAtTime(Runnable r, Object token, long uptimeMillis) | 在某个时间点执行封装Runnable的Message |
final boolean | postAtTime(Runnable r, long uptimeMillis) | 在某个时间点执行封装Runnable的Message |
final boolean | postDelayed(Runnable r, long delayMillis) | 当前时间延迟delayMillis个毫秒后执行封装Runnable的Message |
final void | removeCallbacks (Runnable r) | 移除MessageQueue中的所有封装Runnable的Message对象 |
final void | removeCallbacks(Runnable r, Object token) | |
final void | removeCallbacksAndMessages(Object token) | 当传入的参数为null时,则移除所有的callbacks和messages |
final void | removeMessages(int what) | MessageQueue将Message.what与函数传入的what相同的Message从队列中移除 |
final void | removeMessages(int what, Object object) | MessageQueue将Message.what和Message.obj与函数传入的相同的Message从队列中移除 |
final boolean | sendEmptyMessage(int what) | 发送what的Message |
final boolean | sendEmptyMessageAtTime(int what, long uptimeMillis) | 指定时间,发送what的Message |
final boolean | sendEmptyMessageDelayed(int what, long delayMillis) | 延时发送what的Message |
final boolean | sendMessage(Message msg) | 发送Message |
final boolean | sendMessageAtFrontOfQueue(Message msg) | 立即发送Message到队列,而且是放在队列的最前面 |
boolean | sendMessageAtTime(Message msg, long uptimeMillis) | 指定时间,发送Message |
final boolean | sendMessageDelayed(Message msg, long delayMillis) | 延时,发送Message |
String | toString() |
参考:Android中Handler和Looper的dump方法以及Printer接口的使用
首先,这方法是回调:
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e(TAG, "handler msg.what:" + msg.what);
super.handleMessage(msg);
}
};
用于接收消息。
其次,这个方法也可用于发送消息:
Message message2 = Message.obtain();
message2.what = 102;
handler.handleMessage(message2);
需要注意的是:当我们构造Handler传参为CallBack,我们使用handler.handleMessage()发送消息的时候,handler是没有处理的。只能使用sendMessage();的方式来发送。
public final Message obtainMessage ()
public final Message obtainMessage (int what)
public final Message obtainMessage (int what, Object obj)
public final Message obtainMessage (int what, int arg1, int arg2)
public final Message obtainMessage (int what, int arg1, int arg2, Object obj)
从Handler中获取(一定条件的)Message,复用。因为不需要重新new所以会节省内存,提高效率。
例:
Message msg = handler.obtainMessage();
msg.arg1 = i;
msg.sendToTarget();
Message msg=new Message();
msg.arg1=i;
handler.sendMessage(msg);
Message,Message Queue,Looper和ThreadLocal
是 Handler
实现功能的组成部分
他们分别代表:
对应:一个Looper
,一个MessageQueue
,多个Hanlder
,多个Message
数据模型,用于传递消息。
参数有:
数据结构:消息队列,线程唯一
参考:https://blog.csdn.net/nmyangmo/article/details/82260616
Looper循环队列的核心MessageQueue.next()
:
当MessageQueue
中无消息时,queue.next()
会阻塞在nativePollOnce()
,nativePollOnce()
被阻塞时,主线程会释放CPU资源,进入休眠状态. 直到下个消息到达或者有事务发生,会通过pipe管道写入数据来唤醒主线程工作,就可以继续工作了。
以下三个方法的分析转载自:图解Handler机制
Looper
,也就是一个线程只能调用一次Looper.prepare()
Looper
,那么就创建一个,存到sThreadLocal
中 public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
// 规定了一个线程只有一个Looper,也就是一个线程只能调用一次Looper.prepare()
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 如果当前线程没有Looper,那么就创建一个,存到sThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
MessageQueue
,并供Looper
持有Looper
持有当前线程对象 private Looper(boolean quitAllowed) {
// 创建了MessageQueue,并供Looper持有
mQueue = new MessageQueue(quitAllowed);
// 让Looper持有当前线程对象
mThread = Thread.currentThread();
}
Looper
,通过final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
Message msg = queue.next();
msg.target.dispatchMessage(msg);
msg.recycleUnchecked();
public static void loop() {
// 得到当前线程的Looper对象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 得到当前线程的MessageQueue对象
final MessageQueue queue = me.mQueue;
// 无关代码
......
// 死循环
for (;;) {
// 不断从当前线程的MessageQueue中取出Message,当MessageQueue没有元素时,方法阻塞
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// Message.target是Handler,其实就是发送消息的Handler,这里就是调用它的dispatchMessage方法
msg.target.dispatchMessage(msg);
// 回收Message
msg.recycleUnchecked();
}
}
启动App时,App的入口,是ActivityThread.main
方法:
public static void main(String[] args) {
// 不相干代码
......
// 1.调用Looper.prepareMainLooper,其实也就是调用的Looper.prepare,初始化Looper、MessageQueue等
Looper.prepareMainLooper();
// 2.创建ActivityThread的同时,初始化了成员变量Handler mH
ActivityThread thread = new ActivityThread();
thread.attach(false);
//
if (sMainThreadHandler == null) {
// 把创建的Handler mH赋值给sMainThreadHandler
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// 3.调用Looper.loop()方法,开启死循环,从MessageQueue中不断取出Message来处理
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
可以看到,main方法做了三步:
Looper.prepareMainLooper
,其实也就是调用的Looper.prepare
,初始化Looper
、MessageQueue
等ActivityThread
的同时,初始化了成员变量Handler mH
;Looper.loop()
方法,开启死循环,从MessageQueue
中不断取出Message
来处理第二步,在初始化Handler
过程中:
Handler
对象会得到当前线程的Looper
对象,并判断否为空,让创建的Handler
对象持有Looper
、MessageQueue
、Callback
的引用。
在线程中使用Handler
,需要自己创建Looper
,并调用Looper.prepare
和Looper.loop()
两个方法哦,这就是区别。
参考:Handler后传篇一: 为什么Looper中的Loop()方法不能导致主线程卡死?
首先ANR致使应用卡死的原因是:
所以,looper死循环如果导致崩溃,那么将是堵塞主线程5S导致。
不会。
虽然因为Looper循环内采用了epoll机制,做到了消息队列的阻塞和唤醒,CPU在消息阻塞下会进入休眠状态,但是休眠和死循环完全不是一个东西,CPU的休眠不会阻碍分发。
不会。
只有消息数量达到无限循环的量级,消息才不会被分发完,据我们所知消息数量不会达到无限的量级。
我们知道分发完的事件会在主线程处理哦,耗时5S处理不完,会导致ANR
不会的,消息阻塞期间,CPU会进入休眠
包含如下问题:
内存泄露的原因:线程占用mH,mH占用Activity,致使Activity退出内存泄露
危害:OOM;多次OOM后程序占用内存超过系统限制,FC
解决办法:
1. Handler修改成静态内部类
2. 逻辑保护