Handle
在android
中的意义
Handle
通常用来做主线程和子线程之间的通信
Handle
是Android消息机制中的重要一员
只要是有异步线程与主线程通信都得地方就一定有Handle
Handle
背后通信原理
首先,来创建一个使用Handle
的案例
android.os.Handler handler = new Handler(){
@Override
public void handleMessage(final Message msg) {
//这里接受并处理消息
}
};
//发送消息
handler.sendMessage(message);
handler.post(runnable);
这里发送消息可以发送
message
和runnable
,其实runnable
也是message
,发送runnable
的时候会被封装成message
来发送。
它分为两部分,用来处理和发送消息,发送该例子都是在主线程执行的所以并没有涉及的异步线程的通信,因为发送消息和处理消息都是在主线程,什么时候会有异步通信的情况?就比如你去请求网络后要返回数据更新view
这时候就需要用到handle
,但现在的大部分网络框架基本上在请求到数据后主动切换回主线程了,所以我们可以直接更新view
//发送消息
handler.sendMessage(message);
handler.post(runnable);
要创建
Handle
时,必须要先创建Looper
,创建Looper
的方法是调用Looper.prepare()
,要不然直接创建Handle
会出错
//源码可看可不看
public Handler(Callback callback, boolean async) {
//这里主要是用来做提醒handle如果不及时释放会导致内存溢出,解决方法另起一个类继承handle后者使用静态内部类。之后内部持有Activity的弱引用即可
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//主要是这里
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
为什么我们平时使用没有创建Looper
也不会报错,因为UI主线程已经帮我们创建过了,Looper
会与当前线程进行关联。接下来引出下一个重要的成员MessageQueue
看意思就是一个消息队列,他的作用就是按顺序存放了一堆的待处理的Message
,我们现在发送一个消息handler.sendMessage(message);
发现他最终会调用queue.enqueueMessage(msg)
这里就看的很清楚看到我们发送消息会加入到MessageQueue
这个队列里面,接下来再来看下如何读取消息。
假设我们要在主线程处理消息
android.os.Handler handler = new Handler(){
@Override
public void handleMessage(final Message msg) {
//这里接受并处理消息
}
};
在异步线程(请求网络,创建线程。。等等操作都是在异步线程)一系列操作之后要发行消息给主线程处理handler.sendMessage(message)
(这里其实只是把消息加入到了MessageQueue
消息队列),那主线程是怎么接收到的?
这里就要引出Looper.loop
这个方法,前面的Looper.prepar
方法是为了创建Looper
,这里都得Looper.loop
则是用来做循环,他是什么时候做循环的,来看一个完整的流程
Looper.prepar()
android.os.Handler handler = new Handler(){
@Override
public void handleMessage(final Message msg) {
//这里接受并处理消息
}
};
Looper.loop()
//发送消息
handler.sendMessage(message);
handler.post(runnable);
- 调用
Looper.prepar()
来创建Looper
,Looper
创建成功且与当前线程进行绑定,并且会创建一个空的MessageQueue
消息队列 - 在当前线程创建
handle
来准备处理消息 - 调用
Looper.loop()
后,会生成一个for(;;)
循环,这个无止境的for
循环会不断遍历MessageQueue
如果MessageQueue
不为空就取出message
发送给Handle
处理,如果为空就继续遍历 - 调用
sendMessage()
将一个message
加入到MessageQueue
。
至此大的流程结束,来说一下遍历MessageQueue
时候如何将取出来的数据发送给Handle
去处理的,因为这时发送消息是在异步线程,处理在主线程处理,当Looper
从他的MessageQueue
中取出这条msg
之后,会调用msg
的msg.target.dispatchMessage(msg)
,而msg.targer
就是我们主线程中的Handle
,这样消息就回到了handMessage
中
msg.targer是什么时候赋值为主线程的
Handle
的?就是我们在调用handle.sendMessage(message)
这句话的时候,他不仅仅将message
加入到MessageQueue
还会设置该条message
的targer设置为this
即Handle
handler.sendMessage(message);
handler.sendMessageDelayed(message);
handler.sendMessageAtTime(message);
handle.enqueueMessage();
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
handle
发送消息sendMessage
时候将一条消息加入到MessageQuue
时候,怎么正好是Looper
的MessageQueue
?
在new Handle()
的时候,内部会持有mLooper
,有了Looper
就可以获取到他的MessageQueue
了
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}