Looper、Message、MessageQueue、Handler异步消息处理机制源码分析

本文详细解析了Android中Looper和Handler的工作原理,包括Looper的主要方法prepare()和loop()的作用,以及Handler如何通过发送和处理消息实现线程间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Looper

Looper主要是prepare()和loop()两个方法。

prepare()方法主要是创建Looper和MessageQueue对象,并把Looper对象和线程绑定。

loop()方法主要是从线程绑定的Looper对象中获取MessageQueue消息队列,在死循环中从MessageQueue中循环取消息交给target对象处理。

public static final void prepare() {
		// 获取绑定的Looper对象,如果不为空则抛异常。
		// 这也就说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper对象
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
		// 把Looper对象绑定到当前线程中
        sThreadLocal.set(new Looper(true));
}

private Looper(boolean quitAllowed) {
		// 创建MessageQueue成员变量
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
}

public static void loop() {
		// 获取绑定的Looper对象
        final Looper me = myLooper();
		// 如果me为null则抛异常,说明loop()方法必须在prepare()方法之后调用
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
		// 获取MessageQueue消息队列
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

		// 死循环
        for (;;) {
			// 取出一条消息
            Message msg = queue.next(); // might block
			// 如果消息为null则阻塞
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

			// 把消息交给target处理,这个target就是Handler
            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

			// 释放消息占据的资源
            msg.recycle();
        }
}

public static Looper myLooper() {
		return sThreadLocal.get();
}


2.Handler

Handler主要负责发送和处理消息。

Handler构造方法中获取当前线程的Looper实例,再通过该实例获取到MessageQueue消息队列。这样Handler就与Looper中的MessageQueue关联上了。

跟踪sendMessage()方法:

   public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

   public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
	
   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) {
        // 把Handler对象赋值给target
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

	
   public void dispatchMessage(Message msg) {
        // msg.callback是Runnable对象
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

  /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }


3.Handler post

有时候为了方便,我们会直接写下面的代码:

mHandler.post(new Runnable()
	{
		@Override
		public void run()
		{
			Log.e("TAG", Thread.currentThread().getName());
			mText.setText("hehe");
		}
	});


在run方法中可以写更新UI的代码,其实这个Runnable并没有创建什么线程,而是发送了一条消息,源码如下:

   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;
    }


可以看到,在getPostMessage方法中,得到了一个Message对象,然后将Runnable对象作为callback属性赋值给了msg。sendMessageDelayed方法最后调用了enqueueMessage方法,给msg.target赋值为handler,最终加入MessageQueue。

dispatchMessage方法中由于msg.callback不为null,故会执行handleCallback方法。在该方法中会执行Runnable中的run方法。

   private static void handleCallback(Message msg) {
        msg.callback.run();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值