Handler源码简单梳理

Handler

多少次,迎着冷眼与嘲笑,从没有放弃过心中的理想 让歌词吹去心中所有不悦,怀着冷却的心去讨论下Handler

简单来说,Handler被理解为了四个部分,Handler,Looper,Message以及MessageQueue。Handler用来发送消息和处理消息,Message是用来发送消息的载体,Message一多了就得有东西去对他进行存储,管理,这是就用到了MessageQueue了,消息队列用来存储待处理的Message信息,最后就是Looper了,如果使用默认的构造,就是使用的对应线程的Looper对象。大概到这里,脑子里应该是有一副图。有三个点,分别是Handler,Looper以及MessageQueue。在三条线上传输的东西就是Message对象。自我理解到此结束,还是好好整理下。

相关概念

分别来说说上面说到的四个主要的东西,Handler,Message,Looper和MessageQueue。稍微整理下官方解释。

  • Handler

相关联信息 : 允许我们去发送和处理Message,并且Runnable对象也可以和线程的MessageQueue进行link。每一个Handler对象和一个线程以及这个线程的MessageQueue相关联。
作用 : 1. 将之后要执行的Message添加到消息队列中去;2.在子线程把需要在另一个线程执行的操作加入到消息队列中

  • Looper

一个线程运行一个消息Looper,线程默认是没有消息Looper相关联的,调用prepare来运行这个loop,然后调用loop来处理消息直到loop停止

  • MessageQueue

低级类,保存要处理的消息列表。消息不能够被直接添加到消息队列,需要通过handler对象和Looper

  • Message

被定义用来通过Handler来发送的数据对象。该对象包含两个额外的int类型和一个额外的object类型,方便我们来分配数据

对应关系:

每个线程只有一个Looper
每个MessageQueue由Looper管理,主线程创建会创建一个默认Looper,Looper的创建会自动创建一个MessageQueue。非主线程不会自动创建Looper。

观源码有感

  • Handler ## sendMessage()

对于发送Message对象,最后会发给MessageQueue的enqueueMessage方法,通过一个节点去维护整个消息队列的消息

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

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) {
    // 在入队列的时候,会指定target为当前Handler
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

Handler 发送消息最终会发给MessageQueue对象进行处理

//MessageQueue
boolean enqueueMessage(Message msg, long when) {
    
    //检查是否有target或者当前Message是否正在被使用,此处省略
    synchronized (this) {
        if (mQuitting) {
            IllegalStateException e = new IllegalStateException(
                    msg.target + " sending message to a Handler on a dead thread");
            Log.w(TAG, e.getMessage(), e);
            msg.recycle();
            return false;
        }
        // 标记为正在使用
        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {
            // 如果没有创建头结点,就创建一个头结点
            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;
                }
            }
            // 将Message进行插入
            msg.next = p; // invariant: p == prev.next
            prev.next = msg;
        }

        // We can assume mPtr != 0 because mQuitting is false.
        if (needWake) {
            nativeWake(mPtr);
        }
    }
    return true;
}

MessageQueue的入队列操作通过一个链表进行维护。

  • Handler ## handleMessage()

在Looper在loop的时候,如果Message持有Handler对象(使用obtain()方法创建),就会分发给对应的Handler的dispatchMessage()方法进行处理,dispatchMessage()方法又会分发给 handleMessage方法进行处理

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

这里看到最关键的,handlerMessage方法,也就是调到了dispatchMessage方法就会再去调用handleMessage()方法。

//Looper
public static void loop() {
    final Looper me = myLooper();
    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 (;;) {
        // Looper的死循环,用来处理消息,从队列当中获取
        Message msg = queue.next(); // might block
        if (msg == null) {
            // 没有消息,就结束
            return;
        }
        ...

        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 {
            // 发给对应的Handler进行处理
            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();
    }
}

调查发现,Looper中的loop()方法会调用到dispatchMessage()方法。在上面msg.target.dispatchMessage()方法进行消息的分发处理。其中,target也就是Handler对象,在入队列的时候会将对应的Handler加到target中,也可以通过obtain方法指定。

  • 消息管理

对于消息的管理,通过MessageQueue来对消息进行存储,对于分发,是在Looper中进行的。因为消息队列是由一个头结点进行维护的,所以在Looper的loop方法中会有个死循环,检测到有Message,就会发给对应的Handler。入队列时也会指定对应的Handler,相当于是对上面的一个简单总结。

你可能感兴趣的:(java,开发语言)