目录
1,handler消息循环机制
2,post和sendMessage区别
1,handler消息循环机制
Android中的线程之前要通讯,通常使用的是Handler机制进行通讯,我们开启一个线程通常是不具备线程之间的通讯能力的,想让它具备通讯能力需要在线程中启动Looper,如下
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
这个时候我们可以通过在别的线程关联到LooperThread的looper并实例化Handler进行消息的发送.
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public Handler(Looper looper) {
this(looper, null, false);
}
那它的基本原理是什么呢?
我们先来看看prepare是怎么实现
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
这里会去实例化一个Looper对象,放入sThreadLocal, sThreadLocal的声明是
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
存放过程是
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
这里可以看到,我们通过当前线程去获取Thread中
Thread {
//代码省略...
ThreadLocal.ThreadLocalMap threadLocals = null;
//代码省略...
}
通常来说第一次调用都是null,所以会走createMap(t, value)
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
createMap直接就会创建ThreadLocalMap,并传入刚才的Looper对象,并放入到了线程的threadLocals中了.
这里需要说明一点是每个Thread都有一个 ThreadLocal.ThreadLocalMap threadLocals,它是一个独立的线程存储空间. 在消息循环机制中用来存放Looper对象. 大致模型图如下
image.png
接下来我们会在loop()中去启动消息循环机制
public static void loop() {
//代码省略...
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg);
}
//代码省略...
}
这样就进入了一个循环,会不停的接收queue中的消息,并分发到Message中的target对象上,这里的target是发送消息的Handler.
我们可以看一个发送消息的例子
val handler = Handler()
handler.sendMessage(Message())
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
这里msg.target = this实际上就是Handler对象,所以调用的msg.target.dispatchMessage(msg)实际上也是调用到的Handler的dispatchMessage
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
2,post和sendMessage区别
在使用Handler发送消息的过程中,通常会有两种调用方式,一种是post一个Runnable另外就是sendMessage, 这两种调用本质区别是什么呢. sendMessage调用实际上上面已经说过,最终会走到dispatchMessage的handleMessage处理消息,这里handleMessage有两种情况,一个是mCallback的handleMessage,mCallback是外部传入的Callback,通常实例化Handler的时候会传
val handler = Handler(Handler.Callback {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
})
下面handleMessage(msg)就需要继承Handler进行handleMessage重写处理了.
下面来看看post的情况
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
这里m.callback = r 实际上在dispatchMessage中就会调用
if (msg.callback != null) {
handleCallback(msg);
}
这里处理
private static void handleCallback(Message message) {
message.callback.run();
}
到这就会直接执行掉这个Runnable对象。所以结论就是,post是发送一个带有callback(实际上是Runnable对象),然后在接收消息的线程直接执行掉,而sendMessage是发送一个消息,接收消息的线程收到后会根据消息内容进行相应的处理逻辑.
网友评论