Handler源碼分析

handler 的使用

    //使用匿名內(nèi)部類創(chuàng)建handler
    public static Handler handler=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        };
    };
    //構(gòu)建消息
    Message message = Message.obtain();
    message.what = 1;
    //發(fā)送消息
    handler.sendMessage(message);
    //延時(shí)發(fā)送消息
    handler.sendMessageDelayed(message,1000);
    //直接處理
    handler.post(new Runnable() {
        @Override
        public void run() {

        }
    });

分析1:(創(chuàng)建handler

@Deprecated
public Handler() {
    this(null, false);
}


public Handler(@Nullable Handler.Callback callback, boolean async) {
    ...
    //獲取當(dāng)前線程的Looper
    mLooper = Looper.myLooper();
    //如果沒(méi)有l(wèi)ooper直接拋出異常
    if (mLooper == null) {
        throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
    }
     // Looper.myLooper()作用:獲取當(dāng)前線程的Looper對(duì)象;若線程無(wú)Looper對(duì)象則拋出異常
    // 即 :若線程中無(wú)創(chuàng)建Looper對(duì)象,則也無(wú)法創(chuàng)建Handler對(duì)象
    // 故 若需在子線程中創(chuàng)建Handler對(duì)象,則需先創(chuàng)建Looper對(duì)象
    // 注:可通過(guò)Loop.getMainLooper()可以獲得當(dāng)前進(jìn)程的主線程的Looper對(duì)象

    // 2. 綁定消息隊(duì)列對(duì)象(MessageQueue)
    mQueue = mLooper.mQueue;
    // 獲取該Looper對(duì)象中保存的消息隊(duì)列對(duì)象(MessageQueue)
    // 至此,保證了handler對(duì)象 關(guān)聯(lián)上 Looper對(duì)象中MessageQueue
    mCallback = callback;
    mAsynchronous = async;
    mCallback = callback;
    mAsynchronous = async;
}

分析二(創(chuàng)建Looper)

private static void prepare(boolean quitAllowed) {

    // 1. 判斷sThreadLocal是否為null,否則拋出異常
    //即 Looper.prepare()方法不能被調(diào)用兩次 = 1個(gè)線程中只能對(duì)應(yīng)1個(gè)Looper實(shí)例
    // 注:sThreadLocal = 1個(gè)ThreadLocal對(duì)象,用于存儲(chǔ)線程的變量
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    // 2. 若為初次Looper.prepare(),則創(chuàng)建Looper對(duì)象 & 存放在ThreadLocal變量中
    // 注:Looper對(duì)象是存放在Thread線程里的
    // 源碼分析Looper的構(gòu)造方法->>分析a
    sThreadLocal.set(new Looper(quitAllowed));
}


@Deprecated
public static void prepareMainLooper() {
    //創(chuàng)建looper
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

private Looper(boolean quitAllowed) {
    // 1. 創(chuàng)建1個(gè)消息隊(duì)列對(duì)象(MessageQueue)
    // 即 當(dāng)創(chuàng)建1個(gè)Looper實(shí)例時(shí),會(huì)自動(dòng)創(chuàng)建一個(gè)與之配對(duì)的消息隊(duì)列對(duì)象(MessageQueue)
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}


// 在Android應(yīng)用進(jìn)程啟動(dòng)時(shí),會(huì)默認(rèn)創(chuàng)建1個(gè)主線程(ActivityThread,也叫UI線程)
// 創(chuàng)建時(shí),會(huì)自動(dòng)調(diào)用ActivityThread的1個(gè)靜態(tài)的main()方法 = 應(yīng)用程序的入口
// main()內(nèi)則會(huì)調(diào)用Looper.prepareMainLooper()為主線程生成1個(gè)Looper對(duì)象
public static void main(String[] args) {
    ...

   Looper.prepareMainLooper(); 
        // 1. 為主線程創(chuàng)建1個(gè)Looper對(duì)象,同時(shí)生成1個(gè)消息隊(duì)列對(duì)象(MessageQueue)
        // 方法邏輯類似Looper.prepare()
        // 注:prepare():為子線程中創(chuàng)建1個(gè)Looper對(duì)象
        
        
        ActivityThread thread = new ActivityThread(); 
        // 2. 創(chuàng)建主線程

        Looper.loop(); 
        // 3. 自動(dòng)開(kāi)啟 消息循環(huán) ->>下面將詳細(xì)分析

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

分析三(Looper.loop實(shí)現(xiàn)消息循環(huán))

public static void loop() {

    final Looper me = myLooper();
    //先看有么有l(wèi)ooper,沒(méi)有直接拋異常
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }

    me.mInLoop = true;
    //獲取MessageQueue
    final MessageQueue queue = me.mQueue;

    ...

    //死循環(huán)去獲取MessageQueue里邊的消息
    for (;;) {
        //獲取Message 有可能阻塞在這里
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
       ...
        try {
            //分發(fā)消息 msg.target是一個(gè)Handler
            msg.target.dispatchMessage(msg);
            if (observer != null) {
                observer.messageDispatched(token, msg);
            }
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        }
        //釋放消息占據(jù)的資源
        msg.recycleUnchecked();
    }
}

@UnsupportedAppUsage
Message next() {

    ...
    // 該參數(shù)用于確定消息隊(duì)列中是否還有消息
    // 從而決定消息隊(duì)列應(yīng)處于出隊(duì)消息狀態(tài) or 等待狀態(tài)
    //如果等于-1表示沒(méi)有消息
    int nextPollTimeoutMillis = 0;
    //for循環(huán)
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
        // nativePollOnce方法在native層,若是nextPollTimeoutMillis為-1,此時(shí)消息隊(duì)列處于等待狀態(tài) 
        nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            // 出隊(duì)消息,即 從消息隊(duì)列中取出消息:按創(chuàng)建Message對(duì)象的時(shí)間順序
            if (msg != null && msg.target == null) {
                // Stalled by a barrier.  Find the next asynchronous message in the queue.
                do {
                    prevMsg = msg;
                    //取出下一條消息
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                //延時(shí)的處理,計(jì)算定時(shí)喚醒時(shí)間
                if (now < msg.when) {
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // Got a message.
                    //4.獲取到一條消息,因?yàn)槭窍㈥?duì)列是鏈表結(jié)構(gòu),所以需要調(diào)整一下鏈表
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
                // No more messages.
                // 若 消息隊(duì)列中已無(wú)消息,則將nextPollTimeoutMillis參數(shù)設(shè)為-1
                // 下次循環(huán)時(shí),消息隊(duì)列則處于等待狀態(tài)
                nextPollTimeoutMillis = -1;
            }

            ...
            //5.這里提到 IdleHandler,是個(gè)什么東西?下面會(huì)分析

            //在獲取不到message的時(shí)候才會(huì)走的代碼,也就可以理解為 IdleHandler是消息隊(duì)列空閑(或者主線程空閑)時(shí)候才會(huì)執(zhí)行的Handler。
            //IdleHandler 是一個(gè)接口,只有一個(gè)方法 queueIdle() ,調(diào)用addIdleHandler(IdleHandler handler) 這個(gè)方法的時(shí)候會(huì)將handler添加到list中

            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }

        }



        // While calling an idle handler, a new message could have been delivered
        // so go back and look again for a pending message without waiting.
        nextPollTimeoutMillis = 0;
    }
}

分析四(處理消息)

  //分發(fā)消息
  public void dispatchMessage(Message msg) {

        // 1. 若msg.callback屬性不為空,則代表使用了post(Runnable r)發(fā)送消息
        // 則執(zhí)行handleCallback(msg),即回調(diào)Runnable對(duì)象里復(fù)寫(xiě)的run()
        // 上述結(jié)論會(huì)在講解使用“post(Runnable r)”方式時(shí)講解
        if (msg.callback != null) {
          //當(dāng)使用handler.post()的時(shí)候會(huì)調(diào)用該方法
          //因?yàn)閙sg自帶一個(gè)callback
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }

            // 2. 若msg.callback屬性為空,則代表使用了sendMessage(Message msg)發(fā)送消息(即此處需討論的)
            // 則執(zhí)行handleMessage(msg),即回調(diào)復(fù)寫(xiě)的handleMessage(msg) ->> 分析3
            handleMessage(msg);

        }
    }

    /**
     * 分析3:handleMessage(msg)
     * 注:該方法 = 空方法,在創(chuàng)建Handler實(shí)例時(shí)復(fù)寫(xiě) = 自定義消息處理方式
     **/
    public void handleMessage(Message msg) {
      ... // 創(chuàng)建Handler實(shí)例時(shí)復(fù)寫(xiě)
    }

分析五(發(fā)送一條消息)

    public final boolean sendMessage(@NonNull Message msg) {
        //調(diào)用延時(shí)發(fā)送消息
        return sendMessageDelayed(msg, 0);
    }

    //延時(shí)發(fā)送消息
    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        //獲取消息隊(duì)列對(duì)象
        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(@NonNull MessageQueue queue, @NonNull Message msg,
    long uptimeMillis) {
        // 1. 將msg.target賦值為this
        // 即 :把 當(dāng)前的Handler實(shí)例對(duì)象作為msg的target屬性
        msg.target = this;
        // 請(qǐng)回憶起上面說(shuō)的Looper的loop()中消息循環(huán)時(shí),會(huì)從消息隊(duì)列中取出每個(gè)消息msg,然后執(zhí)行msg.target.dispatchMessage(msg)去處理消息
        // 實(shí)際上則是將該消息派發(fā)給對(duì)應(yīng)的Handler實(shí)例

        // 2. 調(diào)用消息隊(duì)列的enqueueMessage()
        // 即:Handler發(fā)送的消息,最終是保存到消息隊(duì)列
        return queue.enqueueMessage(msg, uptimeMillis);
    }


    boolean enqueueMessage(Message msg, long when) {

        synchronized (this) {
            msg.markInUse();
            msg.when = when;

            Message p = mMessages;
            boolean needWake;
            // 判斷消息隊(duì)列里有無(wú)消息
            // 1. 若無(wú),則將當(dāng)前插入的消息 作為隊(duì)頭 & 若此時(shí)消息隊(duì)列處于等待狀態(tài),則喚醒
            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 {
                 // 2.否則插到鏈表中間,需要移動(dòng)鏈表
            // 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;
            // 鏈表移動(dòng),延時(shí)的消息會(huì)插入到合適的位置
                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;
    }

總結(jié)

1.在應(yīng)用啟動(dòng)的時(shí)候,也就是ActivityThread的main方法里面,創(chuàng)建了Looper和MessageQueue,然后調(diào)用Looper.loop 開(kāi)啟消息循環(huán)
2.消息循環(huán)是這樣的,調(diào)用MessageQueue的next方法,循環(huán)從消息隊(duì)列中取出一條消息,然后交給Handler去處理,一般是回調(diào)handleMessage方法,取不到消息就阻塞,直到下一個(gè)消息入隊(duì)或者其它延時(shí)消息到時(shí)間了就喚醒消息隊(duì)列。
3.消息入隊(duì),通過(guò)調(diào)用handler的sendMessage方法,內(nèi)部是調(diào)用MessageQueue的enqueueMessage方法,進(jìn)行消息入隊(duì),入隊(duì)的規(guī)制是:隊(duì)列沒(méi)有消息,或者要入隊(duì)的消息沒(méi)有設(shè)置delay,或者delay時(shí)間比隊(duì)列頭的消息delay時(shí)間短,則將要入隊(duì)的消息放到隊(duì)列頭,否則就插到隊(duì)列中間,需要移動(dòng)鏈表。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容