Handler 机制学习之Handler、Looper、MessageQueue、Message之间的关系

来源:互联网 发布:博威软件 编辑:程序博客网 时间:2024/04/29 14:09

Handler、Looper、MessageQueue、Message之间的关系

一般创建一个Handler,会得到所在线程的Looper。如果所在线程没有Looper,则会出现运行时异常。

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();           //得到当前线程中的Looper        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;             //当前Looper管理的MessageQueue        mCallback = callback;        mAsynchronous = async;    }

主线程(UI线程)中都有一个Looper,在ActivityThread的main函数中:

public static void main(String[] args) {        SamplingProfilerIntegration.start();        // CloseGuard defaults to true and can be quite spammy.  We        // disable it here, but selectively enable it later (via        // StrictMode) on debug builds, but using DropBox, not logs.        CloseGuard.setEnabled(false);        Environment.initForCurrentUser();        // Set the reporter for event logging in libcore        EventLogger.setReporter(new EventLoggingReporter());        Security.addProvider(new AndroidKeyStoreProvider());        Process.setArgV0("<pre-initialized>");        Looper.prepareMainLooper();         //创建Looper        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }        AsyncTask.init();        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        Looper.loop();             //循环        throw new RuntimeException("Main thread loop unexpectedly exited");    }
Looper用于管理消息MessageQueue,在Looper中,有一个MessageQueue:
final MessageQueue mQueue;private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }

MessageQueue消息队列,维护一系列消息的先进先出。主要有消息进队列enqueueMessage,删除消息removeMessages,下一条消息next等。
Message即使发送的一条一条消息。
Handler通过sendMessage和post等方法,将一条消息放入到消息队列中,
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);    }
然后消息进入消息队列,消息队列中的消息会通过Looper循环取出分发:
public static void loop() {        final Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        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               //取出下一条消息            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);            }            msg.target.dispatchMessage(msg);       //分发消息,通过对应消息的Handler来分发消息            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();        }    }Handler target;   public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);              //是Runnable对象        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }private static void handleCallback(Message message) {        message.callback.run();   //跑Runnable对象的run方法    }/**     * Subclasses must implement this to receive messages.     */    public void handleMessage(Message msg) {              //跑自己写的方法    }    

这样消息就会在相应的Handler中进行相应的处理了。

这样也就很好理解为什么可以在子线程中通过主线程的Handler来发送一条消息,最后被主线程的Handler中HandleMessage处理了。

因为最终都是这样:哪个Handler发的消息,就由自己来处理,而handler在哪个线程中,则使用当前线程的Looper,如果没有,可以自己创建一个。

Enjoy~

今天(2015/10/13)看《深入理解Android卷I》,上面有两句话来总结它们之间的关系,看到的时候一下就觉得都顺了。

分享出来~

(1)Looper中有一个消息队列MessageQueue,里面存储的是一个个待处理的消息Message;

(2)Message中有一个Handler,这个Handler是用来处理Message的。



0 0