从源码角度看handler 消息机制

[toc]
涉及的类主要有这四个
Message
MessageQueue
Looper
Handler

Message 消息对象

1、 主要属性 what obj target ,主要讲讲target
target 就是一个发送和处理消息是绑定的一个handler对象,它是在sendMessage时指定成需要发送消息的那个handler, 在Looper.loop()中被调用去处理消息

MessageQueue 消息队列

1、 主要有两个方法 enqueueMessage() 入队 和 next() 出队两个方法。
enqueueMessage() : 在handler.sendMessage 最终其实就是调用的就是MessageQueue.enqueueMessage(),你可以理解这个方法是一个消息链表添加一个message对象.那它是什么时候回创建的呢?

//handler.sendMessage 最终其实就是调用的就是MessageQueue.enqueueMessage()
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this; //上面说的指定了target
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    //queue 是什么时候创建的?看Handler构造方法
    return queue.enqueueMessage(msg, uptimeMillis);
}

//Handler 构造方法
public Handler(Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class 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; // 在创建handler的时候就指定了MseeageQueue对象的实例,从这里也可以知道MessageQueue实例是在Looper对象里面。
    mCallback = callback;
    mAsynchronous = async;
}

截止目前,还是没有回答上一个问题,什么时候创建的queue。我们继续看下一个对象Looper

Looper 消息泵

这个对象其实就是一个消息泵,不停的在处理消息。我们需要关心的两个方法 Looper.prepare() 和 Looper.loop()
1、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 内部使用了一个类似于map来维护
}

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

可以看到这个Only one Looper may be created per thread ,一个线程只能创建一个looper ,然后调用了sThreadLocal.set(new Looper(quitAllowed)) 在Looper对象的构造方法中,就会创建一个Messagequeue对象

2、Looper.loop()
这个是loop()方法的全部内容

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 (;;) { // 无限for循环,不停的获取消息,调用target对象身上的dispatchMessage
        //出队获取到消息对象
        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
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

        final long traceTag = me.mTraceTag;
        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
        final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        final long end;
        try {
            // 获取到绑定在Message消息身上的Handler对象,调用它的dispatchMessage方法,处理消息
            msg.target.dispatchMessage(msg);
            end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        if (slowDispatchThresholdMs > 0) {
            final long time = end - start;
            if (time > slowDispatchThresholdMs) {
                Slog.w(TAG, "Dispatch took " + time + "ms on "
                        + Thread.currentThread().getName() + ", h=" +
                        msg.target + " cb=" + msg.callback + " msg=" + msg.what);
            }
        }

        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.recycleUnchecked();
    }
}

可能大家还是很疑惑,我们使用handler时,从来没有创建过Looper.prepare方法,那么looper对象实例是什么时候被创建的呢?
其实在创建UI线程(ActivityThread )时,就已经创建了Looper对象

public static void main(String[] args) {
    /...
    Process.setArgV0("");

    Looper.prepareMainLooper(); //内部调用了Looper.prepare

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    Looper.loop();

}

4、Handler 消息处理者
截止这里就可以看到Handler的工作机制了,sendMessage发送消息,其实就是一个入队操作,而dispatchMessage就是处理消息,我们通常的handleMessage就是在这里被调用的。

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

截止目前我们可以大概理解Handler消息机制大概是这样的:
在UI线程被创建时,ActivityThread 的main方法就会创建一个Looper对象,并启动消息泵Looper.loop(),并创建一个MessageQueue对象,在我们创建Handler的时候,获取到Looper对象和它身上的queue对象,并在Handler.sendMessage()方法调用mQueue对象的入队方法。Looper.loop()内部维护这一个无限for循环,不断的从queue.next() 方法,获取到Messge对象并调用msg.target.dispatchMessage(msg)处理消息。

你可能感兴趣的:(从源码角度看handler 消息机制)