Handler、Looper、MessageQueue的关系

在日常开发中我们经常用到Handler,用来处理、传递消息而Handler中内部怎么实现,它与Looper、MessageQueue到底有什么关系确说不上来。

先看下大体流程图:

handler.jpg

MessageQueue内部维护了一个Message的队列,我们通过Handler将消息Message发送到Looper中的MessageQueue,通过不断循环的Looper从MessageQueue中取出消息进行分发与执行。下面我们通过源码具体分析:

    //不传参数构造方法
    Handler handler = new Handler();

最后会调用Handler中的这个构造方法

    public Handler(Callback callback, boolean async) {
        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 that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

在此构造方法主要对Handler 中的mLooper与mQueue赋值。
mLooper = Looper.myLooper(); 获取的是当前线程的Looper
mQueue获取的是Looper中的 MessageQueue。
Handler发送消息

    handler.sendMessage()

最后会调用Handler中

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

在Handler中的enqueueMessage调用了MessageQueue中的enqueueMessage

 boolean enqueueMessage(Message msg, long when) {
       省略......      
        synchronized (this) {
            if (mQuitting) {
                //线程退出 回收消息
                msg.recycle();
                return false;
            }
            //标记消息为再用状态
            msg.markInUse();
            //设置等待时长
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                 needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

这里主要将Message添加入队列
最后在当前线程中Looper.loop()中处理Message

public static void loop() {
        final Looper me = myLooper();
       ......
        for (;;) {
            Message msg = queue.next(); // might block
           ......
            try {
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
          ......
       }
    }

最后会调用msg.target.dispatchMessage(msg)分发消息,msg.target是传入的是Handler,所以最后会调用Handler的dispatchMessage方法分发。
再说下Looper的启动,在我们的主线程UI线程中,Looper是由ActivityThread启动,我们在看下ActivityThread的main()方法
/frameworks/base/core/java/android/app/ActivityThread.java

  public static void main(String[] args) {
        .....
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        ......
        Looper.loop();
        ......
}

我们可以看到在ActivityThread的main方法中实例化了ActivityThread,并且在主线程中调用Looper.prepareMainLooper();
最后调用了Looper的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));
    }

在此方法为sThreadLocal 赋值实例化的Looper,在ActivityThread中最后调用Looper.loop(); 循环处理消息。
从ActivityThread的main函数中可得知,如果在子线程使用Handler需要调用Looper.prepare() 后调用Looper.loop()才可以传递处理Message

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值