先看一下源碼中對(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)容。
此類(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)
猜你還喜歡下面的內(nèi)容