最近一直在学习多线程,handler的作用真的很重要啊,所以保存这篇看的蛮懂的。
Handler mHandler = newHandler();
mHandler.post(newRunnable() {
@Overridepublic voidrun() {
showContentView(contentView);
}
});
下面我们先来看一下这个方法是怎么执行的
首先:
public final booleanpost(Runnable r)
{return sendMessageDelayed(getPostMessage(r), 0);
}
它把Runnable重新封装了一遍然后调用了sendMessageDelayed方法
看一下是怎么封装的
private finalMessage getPostMessage(Runnable r) {
Message m=Message.obtain();
m.callback=r;returnm;
}
看到了吧,用过Handler的都知道Message是用来记录信息的最小单元,这里把Runnable封装到一个Message对象并返回
然后:
public final boolean sendMessageDelayed(Message msg, longdelayMillis)
{if (delayMillis < 0) {
delayMillis= 0;
}return sendMessageAtTime(msg, SystemClock.uptimeMillis() +delayMillis);
}
这里就是对delayMillis做了一下有效性检测
紧接着:
public boolean sendMessageAtTime(Message msg, longuptimeMillis)
{boolean sent = false;
MessageQueue queue=mQueue;if (queue != null) {
msg.target= this;
sent=queue.enqueueMessage(msg, uptimeMillis);
}else{
RuntimeException e= newRuntimeException(this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}returnsent;
}
Handler对象把Message压到了MessageQueue队列里面
貌似方法到这里就return了,那么压进去的信息是怎么发送的呢? 这得从Handler的原理说起了。有很多人已经写了这个原理了,就不在做阐述
可以查看这篇博客《android handler线程原理详详解》
然后我们去分发信息的点去看是如何执行的
public static final voidloop() {
Looper me=myLooper();
MessageQueue queue=me.mQueue;while (true) {
Message msg= queue.next(); //might block//if (!me.mRun) {//break;//}
if (msg != null) {if (msg.target == null) {//No target is a magic identifier for the quit message.
return;
}if (me.mLogging!= null) me.mLogging.println(">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " +msg.what
);
msg.target.dispatchMessage(msg);if (me.mLogging!= null) me.mLogging.println("<<<<< Finished to " + msg.target + " "
+msg.callback);
msg.recycle();
}
}
}
Looper对象把MessageQueue里面的Message逐个取出来,注意看msg.target.dispatchMessage(msg)这一句。
Message类定义了一个字段target,这个字段就是Handler类型,存的对象就是创建这个message的对象,也就是我们的handler对象。
然后就是调用我们的handler里面的dispatchMessage(msg)方法了
public voiddispatchMessage(Message msg) {if (msg.callback != null) {
handleCallback(msg);
}else{if (mCallback != null) {if(mCallback.handleMessage(msg)) {return;
}
}
handleMessage(msg);
}
}
看到没有,一开始我们的Runnable传进来,然后调用GetPostMessage方法把Runnable赋值给了Massage里面的callback,
在分发的时候判断如果callback不是null就调用handleCallback(msg)方法。
最后,执行我们的线程。
private final voidhandleCallback(Message message) {
message.callback.run();
}
---------------------------------------------------------小小分割线----------------------------------------------------------
意义:
到了这里,我们发现貌似这玩意也就是转了一圈又调用了线程的run而已么,那么这又有什么用呢。
如果我们给handler传入的是一个message,那么最后会调用我们的handler的handleMessage(Message)方法,然后我们再去判断最后再去处理
,但是我们用runnable可以直接传入如何操作的对象,不需要再接收到消息后再去判断message的what然后选择做什么操作,从代码清晰的角度,
我也觉得这样子会比在判断一遍要清晰,容易理解很多。
---------------------------------------------------------小小分割线----------------------------------------------------------
所解决的问题:
请看博文第一段代码,这里面的runnable执行了一个setContentView(View),这里的handler是在onActivityResult里面调用的,也就是注销后重新登录回到主页面的这种情况,这个view里面包含了一些fragment,然后activity里面绑定fragment是需要是活动状态的,如果不用handler,直接执行,在onActivityResult方法执行期间activity还是在onPause状态,所以在程序执行到添加fragment的时候报错了,而用了handler就能保证这段代码最后会在activity处于活动状态既UI线程里面执行了。
原文链接:http://blog.youkuaiyun.com/panjidong_3/article/details/7890383
本文详细解析了Java Handler的post方法的工作流程,从创建Handler、封装Runnable到MessageQueue的分发,再到最终执行run方法。通过实例说明了Handler在处理线程间通信,特别是在线程恢复如onActivityResult时避免UI线程错误的重要性。通过理解Handler的运作机制,有助于提升Android应用的多线程编程能力。

被折叠的 条评论
为什么被折叠?



