来自:http://blog.csdn.net/panjidong_3/article/details/7890383
感谢原作者。
====================================================================================
最近公司项目做了一些比较大的重构,很多地方都用了Handler.post(Runnable r),这个方法,比如这一段
- Handler mHandler = new Handler();
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- showContentView(contentView);
Handler mHandler = new Handler();mHandler.post(new Runnable() { @Override public void run() { showContentView(contentView);}});下面我们先来看一下这个方法是怎么执行的 首先:
- public final boolean post(Runnable r)
- return sendMessageDelayed(getPostMessage(r), 0);
public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0);}它把Runnable重新封装了一遍然后调用了sendMessageDelayed方法 看一下是怎么封装的
- private final Message getPostMessage(Runnable r) {
- Message m = Message.obtain();
- m.callback = r;
- return m;
private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }看到了吧,用过Handler的都知道Message是用来记录信息的最小单元,这里把Runnable封装到一个Message对象并返回 然后:
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- if (delayMillis < 0) {
- delayMillis = 0;
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }这里就是对delayMillis做了一下有效性检测 紧接着:
- public boolean sendMessageAtTime(Message msg, long uptimeMillis)
- boolean sent = false;
- MessageQueue queue = mQueue;
- if (queue != null) {
- msg.target = this;
- sent = queue.enqueueMessage(msg, uptimeMillis);
- else {
- RuntimeException e = new RuntimeException(
- this + " sendMessageAtTime() called with no mQueue");
- Log.w("Looper", e.getMessage(), e);
- return sent;
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }Handler对象把Message压到了MessageQueue队列里面 貌似方法到这里就return了,那么压进去的信息是怎么发送的呢? 这得从Handler的原理说起了 。有很多人已经写了这个原理了,就不在做阐述 可以查看这篇博客 然后我们去分发信息的点去看是如何执行的
- public static final void loop() {
- 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();
public static final void loop() { 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 void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- handleMessage(msg);
public void dispatchMessage(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 void handleCallback(Message message) {
- message.callback.run();
private final void handleCallback(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线程里面执行了 。