成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

android源碼分析-深入looper handler message

DobbyKim / 2181人閱讀

摘要:在這里表示的是不允許退出。這之后會(huì)調(diào)用到進(jìn)入實(shí)質(zhì)性的工作函數(shù)中。看到了吧,由于函數(shù)運(yùn)行在主線程中,因此以上這些都是在主線程中運(yùn)行的代碼。注意,這個(gè)是排他性的,如果前面的可以執(zhí)行就不會(huì)走后面的?,F(xiàn)在比較清楚了吧,整個(gè)消息循環(huán)是如何運(yùn)轉(zhuǎn)的。

本來(lái)是不想寫這篇文章的,但是很早以前看過(guò)的東西容易遺忘,希望還是給自己一個(gè)記錄吧,另外此篇希望能夠?qū)懙纳钊胍恍?br>looper是什么就不介紹了吧,一個(gè)線程的消息泵,handler是消息的操作者,messagequeue是消息隊(duì)列。
我們從源頭開始看起,activity里的主ui線程就是ActivityThread mMainThread。這個(gè)ActivityThread的main函數(shù)會(huì)在程序創(chuàng)建的時(shí)候被調(diào)用,那么看下內(nèi)部:

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        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());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("");

        Looper.prepareMainLooper();

        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();

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

首先走了Looper.prepareMainLooper();這個(gè)是與普通線程創(chuàng)建looper不同的地方,普通的都是prepare方法調(diào)用。那么看看里面:

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

還是prepare,但是傳遞的參數(shù)是false。在這里表示的是不允許退出。再來(lái)就是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));
    }

存儲(chǔ)線程本地對(duì)象中一個(gè)新的looper。同時(shí)可以看到,如果已經(jīng)存在了這個(gè)線程本地對(duì)象,那么直接報(bào)錯(cuò),也就是說(shuō)一個(gè)線程只允許一個(gè)looper存在。
回到ActivityThread的main,初始化好之后就是sMainThreadHandler = thread.getHandler();這個(gè)getHandler里直接返回的是mH,其實(shí)就是一個(gè)Handler的子類H。這個(gè)H是個(gè)很長(zhǎng)的類,就是定義好的對(duì)activity默認(rèn)相應(yīng)的各項(xiàng)。
這之后會(huì)調(diào)用到Looper.loop();進(jìn)入實(shí)質(zhì)性的工作函數(shù)中。

    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 traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }

            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的構(gòu)造函數(shù)里就創(chuàng)建了MessageQueue:

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

那么這個(gè)loop函數(shù)中就直接取過(guò)來(lái)用,后面是個(gè)死循環(huán),不斷的通過(guò)queue.next()獲取新的消息,并最終調(diào)用msg.target.dispatchMessage(msg);來(lái)處理。至此looper分析完了。下面看看Message的msg.target.dispatchMessage(msg);是怎么調(diào)用的:
看到message的時(shí)候,他的target就是Handler。這下子串上了吧,在looper的loop函數(shù)循環(huán)中枚舉新message,并交給message里的Handler的dispatchMessage函數(shù)處理。那么好吧,我們回顧下,在發(fā)送message的時(shí)候,一般先obtain獲取一個(gè)消息,我們看看:

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

看起來(lái)像鏈表是吧,每次取得時(shí)候?qū)Pool給m,sPool移動(dòng)到下一個(gè),然后將sPoolSize減一,最后返回m。再看下回收部分:

    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

這里將自己賦值給sPool,然后sPoolSize++,看到這里應(yīng)當(dāng)明白,其實(shí)就是個(gè)鏈表的應(yīng)用,保證sPool指向的是空閑的message的第一個(gè)。
然后呢,應(yīng)用的時(shí)候會(huì)調(diào)用Handler的sendMessage函數(shù),并且將參數(shù)設(shè)置為剛才獲取到的空閑message,對(duì)吧。那么我們看看這個(gè)sendMessage,最終會(huì)調(diào)用到sendMessageAtTime中:

    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);
    }

這里出現(xiàn)了MessageQueue,然后會(huì)走到enqueueMessage:

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

第一句就是msg.target = this;,清楚了吧,這里將message的target賦值為handler自身。那么回到loop這個(gè)函數(shù)中,會(huì)走到msg.target.dispatchMessage(msg);這句話,實(shí)際上就是在走h(yuǎn)andler的msg.target.dispatchMessage。再進(jìn)入到handler中看看這個(gè)dispatchMessage:

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

能看到什么?先試圖調(diào)用message的callback,如果沒(méi)有則試圖調(diào)用自身的mCallback的handleMessage,如果還沒(méi)有,好吧,直接走h(yuǎn)andleMessage。依次看一下,首先是handleCallback:

    private static void handleCallback(Message message) {
        message.callback.run();
    }

這個(gè)callback是個(gè)什么呢?可以通過(guò)Message的obtain看到:

    public static Message obtain(Handler h, Runnable callback) {
        Message m = obtain();
        m.target = h;
        m.callback = callback;

        return m;
    }

一個(gè)runnable,那么這個(gè)runnable是何時(shí)被賦值的呢?看Handler中:

    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

看到了吧,這里在執(zhí)行post的時(shí)候給的runnable就是這個(gè)callback。那么再想想,我們?cè)趯懘a的時(shí)候,很多時(shí)候都會(huì)走一個(gè)handler的post或者postDelayed,執(zhí)行一段代碼在主線程中,這個(gè)傳遞進(jìn)來(lái)的runnable就是message的callback了。順便說(shuō)下,View里的post也是調(diào)用的這個(gè)東西。
下面是Handler自身的mCallback了,在構(gòu)造Handler的時(shí)候可以指定一個(gè)callback傳遞進(jìn)來(lái),這個(gè)Callback是這樣定義的:

    public interface Callback {
        public boolean handleMessage(Message msg);
    }

指定的話就會(huì)走這個(gè)標(biāo)準(zhǔn)的回調(diào),否則最后會(huì)走Handler的handleMessage,這個(gè)才是我們最常用的繼承下來(lái)的函數(shù)??吹搅税?,由于loop函數(shù)運(yùn)行在主線程中,因此以上這些都是在主線程中運(yùn)行的代碼。注意,這3個(gè)是排他性的,如果前面的可以執(zhí)行就不會(huì)走后面的。
現(xiàn)在比較清楚了吧,整個(gè)消息循環(huán)是如何運(yùn)轉(zhuǎn)的。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66767.html

相關(guān)文章

  • android源碼分析-深入消息機(jī)制

    摘要:輔助功能類,提供接口向消息池中發(fā)送各類消息事件,并且提供響應(yīng)消息的機(jī)制。進(jìn)入消息泵循環(huán)體,以阻塞的方式獲取待處理消息。執(zhí)行消息的派發(fā)。并且將返回值保存在了。我們深入下去看看層的部分,在這里明顯生成了一個(gè)新的,并且將地址作為返回值返回了。 概述 android里的消息機(jī)制是非常重要的部分,這次我希望能夠系統(tǒng)的剖析這個(gè)部分,作為一個(gè)總結(jié)。首先這里涉及到幾個(gè)部分,從層次上看,分為java層和...

    superw 評(píng)論0 收藏0
  • Android異步消息機(jī)制

    摘要:在子線程中發(fā)送消息,主線程接受到消息并且處理邏輯。也稱之為消息隊(duì)列,特點(diǎn)是先進(jìn)先出,底層實(shí)現(xiàn)是單鏈表數(shù)據(jù)結(jié)構(gòu)得出結(jié)論方法初始話了一個(gè)對(duì)象并關(guān)聯(lián)在一個(gè)對(duì)象,并且一個(gè)線程中只有一個(gè)對(duì)象,只有一個(gè)對(duì)象。 目錄介紹 1.Handler的常見的使用方式 2.如何在子線程中定義Handler 3.主線程如何自動(dòng)調(diào)用Looper.prepare() 4.Looper.prepare()方法源碼分析...

    王晗 評(píng)論0 收藏0
  • Android異步消息機(jī)制

    摘要:在子線程中發(fā)送消息,主線程接受到消息并且處理邏輯。子線程往消息隊(duì)列發(fā)送消息,并且往管道文件寫數(shù)據(jù),主線程即被喚醒,從管道文件讀取數(shù)據(jù),主線程被喚醒只是為了讀取消息,當(dāng)消息讀取完畢,再次睡眠。 目錄介紹 1.Handler的常見的使用方式 2.如何在子線程中定義Handler 3.主線程如何自動(dòng)調(diào)用Looper.prepare() 4.Looper.prepare()方法源碼分析 5....

    blair 評(píng)論0 收藏0
  • Android之消息機(jī)制問(wèn)題

    摘要:通過(guò)向消息池發(fā)送各種消息事件通過(guò)處理相應(yīng)的消息事件。消息泵通過(guò)不斷地從中抽取,按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者。也稱之為消息隊(duì)列,特點(diǎn)是先進(jìn)先出,底層實(shí)現(xiàn)是單鏈表數(shù)據(jù)結(jié)構(gòu)。目錄介紹 6.0.0.1 談?wù)勏C(jī)制Hander作用?有哪些要素?流程是怎樣的?簡(jiǎn)單說(shuō)一下你的看法! 6.0.0.2 為什么一個(gè)線程只有一個(gè)Looper、只有一個(gè)MessageQueue,可以有多個(gè)Handler? 6...

    番茄西紅柿 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<