美文网首页
Handler核心代码解析

Handler核心代码解析

作者: 济公大将 | 来源:发表于2018-02-26 13:22 被阅读0次

1 Looper.prepare

if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
}
//创建Looper对象,并确保一个线程只含有一个Looper对象
sThreadLocal.set(new Looper(quitAllowed));

//创建Looper对象
private Looper(boolean quitAllowed) {
   //初始化消息队列
   mQueue = new MessageQueue(quitAllowed);
   //初始化线程对象为当前线程
   mThread = Thread.currentThread();
}

2 new Handler()

    //没有指定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());
            }
        }
        //取当前的Looper,如果是主线程会在ActivityThread中通过Looper.prepareMainLooper();创建与主线程关联的对象
        //如果是子线程,则需要在创建Handler之前手动通过Looper.prepare创建Looper,否则会抛出异常
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        //用Looper的消息队列赋值
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

3 获取消息

    //使用的消息池的概念,能减少重复创建Message对象
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

4 发送消息

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
       //消息和Handler进行关联
       msg.target = this;
       if (mAsynchronous) {
           msg.setAsynchronous(true);
       }
       return queue.enqueueMessage(msg, uptimeMillis);
   }
   //下面是对消息队列的一个操作
   boolean enqueueMessage(Message msg, long when) {
       //消息必须关联Handler
       if (msg.target == null) {
           throw new IllegalArgumentException("Message must have a target.");
       }
       //消息没有在使用中
       if (msg.isInUse()) {
           throw new IllegalStateException(msg + " This message is already in use.");
       }

       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) {
               // New head, wake up the event queue if blocked.
               msg.next = p;
               mMessages = msg;
               needWake = mBlocked;
           } else {
               // Inserted within the middle of the queue.  Usually we don't have to wake
               // up the event queue unless there is a barrier at the head of the queue
               // and the message is the earliest asynchronous message in the queue.
               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;
           }

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

5 响应handler的handleMessage

    //线程必须调用这个方法以实现消息队列的响应
    //在ActivityThread中调用了Looper.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 (;;) {
            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 {
                //最终在这里响应Handler的handleMessage
                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();
        }
    }

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

相关文章

网友评论

      本文标题:Handler核心代码解析

      本文链接:https://www.haomeiwen.com/subject/ptcyxftx.html