AndroidLooper用法及分析-創(chuàng)新互聯(lián)

先看一下源碼中對(duì)looper進(jìn)行的解釋?zhuān)?br />在這里插入圖片描述
根據(jù)注釋內(nèi)容,可以了解到,消息循環(huán)的交互情況都是通過(guò)handler進(jìn)行的。
再不和handler搭配的情況下,通常都是以looper.prepare和looper.loop這種方式成對(duì)出現(xiàn)的,使在這兩句話中間執(zhí)行的內(nèi)容都是通過(guò)looper進(jìn)行通信執(zhí)行相應(yīng)內(nèi)容。

成都創(chuàng)新互聯(lián)長(zhǎng)期為1000+客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為孝昌企業(yè)提供專(zhuān)業(yè)的做網(wǎng)站、網(wǎng)站建設(shè),孝昌網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

此類(lèi)還有對(duì)api實(shí)施進(jìn)行注釋描述,貼上來(lái)也一起看一下吧。
在這里插入圖片描述
這部分描述可以看到,looper基于MessageQueue并可以影響任務(wù)隊(duì)列的狀態(tài)。通常都是在MessageQueue或者Handler上進(jìn)行定義,這里講了looper的作用和其定義的時(shí)機(jī)。

個(gè)人理解:
looper通常都是在非主線程的時(shí)候使用讓部分代碼塊可以作用在主線程,進(jìn)行ui更新等一些操作。用到的地方有很多,在activityThread當(dāng)中可以看到很多l(xiāng)ooper的影子。在什么時(shí)候用源碼的注釋上面解釋的挺清晰了。
該類(lèi)中中在跨進(jìn)程部分運(yùn)用的都是binder進(jìn)行通信,threadlocal進(jìn)行線程管理。

此類(lèi)中不對(duì)外暴露的方法不進(jìn)行介紹。
----------------------------------------------------------我是分割線----------------------------------------------------------

方法介紹

prepare()方法最終會(huì)傳遞true到 prepare(boolean quitAllowed)方法當(dāng)中,這里直接看 prepare(boolean quitAllowed)方法。
在這里插入圖片描述
這里可以看到該方法會(huì)優(yōu)先判斷threadlocal線程池里面是否為null,里面有數(shù)據(jù)的時(shí)候就會(huì)拋出運(yùn)行異常(因?yàn)榇磉@個(gè)時(shí)候looper有正在運(yùn)行,必須要保持一個(gè)looper),里面沒(méi)有數(shù)據(jù)的話就會(huì)把傳遞過(guò)來(lái)的boolean類(lèi)型放到looper對(duì)象的參數(shù)中,然后設(shè)置到線程池里去運(yùn)用。

getMainLooper方法,會(huì)鎖住looper類(lèi),然后返回當(dāng)前正在使用的looper。

myLooper()方法,會(huì)從當(dāng)前的threadlocal獲取內(nèi)容并進(jìn)行返回。

showSlowLog(long threshold, long measureStart, long measureEnd,String what, Message msg)方法,傳遞過(guò)來(lái)的參數(shù)如果還在倒計(jì)時(shí),那么就打印log并返回為true,打印的log內(nèi)容見(jiàn)下圖:在這里插入圖片描述

myLooper()方法,會(huì)獲取當(dāng)前threadllocal里面的內(nèi)容進(jìn)行return。

myQueue()方法,執(zhí)行mylooper方法獲取其mQueue變量進(jìn)行retun。

Looper(boolean quitAllowed)方法,實(shí)例化的時(shí)候會(huì)把傳遞過(guò)來(lái)參數(shù)作為實(shí)例化MessageQueue的參數(shù),并且當(dāng)前的線程會(huì)獲取當(dāng)前的線程,表述的可能不太清晰看圖吧:
在這里插入圖片描述

isCurrentThread()方法,該方法會(huì)判斷l(xiāng)ooper當(dāng)前的sThread常量和Thread.currentThread()返回的變量是否相等(==)

setMessageLogging(@Nullable Printer printer)方法,會(huì)把傳遞過(guò)來(lái)的Printer 賦值給當(dāng)前l(fā)ooper的mLogging變量。Printer 的用法還請(qǐng)?jiān)倏聪嚓P(guān)介紹~

quit()方法,執(zhí)行l(wèi)ooper當(dāng)前queue的quit(blooean)方法,傳遞false過(guò)去。

quitSafely()方法,同樣執(zhí)行queue的quit方法,但是會(huì)傳遞true過(guò)去,至于這個(gè)方法傳遞不同參數(shù)的含義請(qǐng)到queue分析當(dāng)中去看。

getThread()方法,return looper當(dāng)前的mThread。

getQueue()方法,return looper當(dāng)前的mQueue。

dump(@NonNull Printer pw, @NonNull String prefix) 方法,會(huì)用傳遞過(guò)來(lái)的pw打印出prefix內(nèi)容,然后執(zhí)行mqueue.dump方法,該方法第三個(gè)參數(shù)為null。

dump(@NonNull Printer pw, @NonNull String prefix, Handler handler)方法,會(huì)用傳遞過(guò)來(lái)的pw打印出prefix內(nèi)容,然后執(zhí)行mqueue.dump方法,該方法第三個(gè)參數(shù)為傳遞過(guò)來(lái)的handler。具體執(zhí)行內(nèi)容也請(qǐng)看queue里面的dump方法。(該方法為hide,寫(xiě)多了)

toString()方法,這個(gè)就看圖片吧。
在這里插入圖片描述

prepareMainLooper()方法,會(huì)把false傳遞到要執(zhí)行的prepare方法中。然后synchronized-- looper類(lèi) 判斷當(dāng)前的looper是否為null,為null的話就走myLooper方法進(jìn)行獲取,不為null則會(huì)拋出IllegalStateException。

loop方法內(nèi)容比較多,也需要結(jié)合代碼進(jìn)行查看。先進(jìn)行大概描述,然后再結(jié)合圖片里面的代碼進(jìn)行查看。
looper.loop會(huì)先執(zhí)行myLooper方法獲取looper判斷是否為null。獲取當(dāng)前l(fā)ooper的mQueue,進(jìn)入到無(wú)限循環(huán)當(dāng)中,獲取queue里面的message。如果message為null就return,不為null時(shí)就會(huì)獲取當(dāng)前的observer,獲取當(dāng)前message里面的相關(guān)時(shí)間和tag用來(lái)判斷message的執(zhí)行時(shí)間。把相關(guān)tag放到trace.tracebegin當(dāng)中進(jìn)行跟蹤。判斷當(dāng)前observer是否為空不為空的話執(zhí)行相應(yīng)方法,首先執(zhí)行messageDispatchStarting方法,在message.target執(zhí)行dispatchMessage之后執(zhí)行observer.messageDispatched方法,如果這個(gè)時(shí)候走到catch里面了,會(huì)執(zhí)行observer的dispatchingThrewException方法。trycatch最終都會(huì)跟蹤該消息。判斷時(shí)間打印出相應(yīng)的log,最終會(huì)執(zhí)行message.recycleUnchecked()重置message 的內(nèi)容和Binder.clearCallingIdentity()方法清理標(biāo)識(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.");
        }
        if (me.mInLoop) {Slog.w(TAG, "Loop again would have the queued messages be executed"
                    + " before this one completed.");
        }

        me.mInLoop = true;
        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();

        // Allow overriding a threshold with a system prop. e.g.
        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        boolean slowDeliveryDetected = false;

        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);
            }
            // Make sure the observer won't change while processing a transaction.
            final Observer observer = sObserver;

            final long traceTag = me.mTraceTag;
            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
            if (thresholdOverride >0) {slowDispatchThresholdMs = thresholdOverride;
                slowDeliveryThresholdMs = thresholdOverride;
            }
            final boolean logSlowDelivery = (slowDeliveryThresholdMs >0) && (msg.when >0);
            final boolean logSlowDispatch = (slowDispatchThresholdMs >0);

            final boolean needStartTime = logSlowDelivery || logSlowDispatch;
            final boolean needEndTime = logSlowDispatch;

            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            Object token = null;
            if (observer != null) {token = observer.messageDispatchStarting();
            }
            long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
            try {msg.target.dispatchMessage(msg);
                if (observer != null) {observer.messageDispatched(token, msg);
                }
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } catch (Exception exception) {if (observer != null) {observer.dispatchingThrewException(token, msg, exception);
                }
                throw exception;
            } finally {ThreadLocalWorkSource.restore(origWorkSource);
                if (traceTag != 0) {Trace.traceEnd(traceTag);
                }
            }
            if (logSlowDelivery) {if (slowDeliveryDetected) {if ((dispatchStart - msg.when)<= 10) {Slog.w(TAG, "Drained");
                        slowDeliveryDetected = false;
                    }
                } else {if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                            msg)) {// Once we write a slow delivery log, suppress until the queue drains.
                        slowDeliveryDetected = true;
                    }
                }
            }
            if (logSlowDispatch) {showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
            }

            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對(duì)外暴露的方法基本都已經(jīng)寫(xiě)出。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

本文標(biāo)題:AndroidLooper用法及分析-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)地址:http://www.bm7419.com/article6/dcdoig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、外貿(mào)網(wǎng)站建設(shè)、軟件開(kāi)發(fā)網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)公司、網(wǎng)站營(yíng)銷(xiāo)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)