先看一下源碼中對looper進行的解釋,
根據(jù)注釋內(nèi)容,可以了解到,消息循環(huán)的交互情況都是通過handler進行的。
再不和handler搭配的情況下,通常都是以looper.prepare和looper.loop這種方式成對出現(xiàn)的,使在這兩句話中間執(zhí)行的內(nèi)容都是通過looper進行通信執(zhí)行相應內(nèi)容。
此類還有對api實施進行注釋描述,貼上來也一起看一下吧。
這部分描述可以看到,looper基于MessageQueue并可以影響任務隊列的狀態(tài)。通常都是在MessageQueue或者Handler上進行定義,這里講了looper的作用和其定義的時機。
個人理解:
looper通常都是在非主線程的時候使用讓部分代碼塊可以作用在主線程,進行ui更新等一些操作。用到的地方有很多,在activityThread當中可以看到很多l(xiāng)ooper的影子。在什么時候用源碼的注釋上面解釋的挺清晰了。
該類中中在跨進程部分運用的都是binder進行通信,threadlocal進行線程管理。
此類中不對外暴露的方法不進行介紹。
----------------------------------------------------------我是分割線----------------------------------------------------------
prepare()方法最終會傳遞true到 prepare(boolean quitAllowed)方法當中,這里直接看 prepare(boolean quitAllowed)方法。
這里可以看到該方法會優(yōu)先判斷threadlocal線程池里面是否為null,里面有數(shù)據(jù)的時候就會拋出運行異常(因為代表這個時候looper有正在運行,必須要保持一個looper),里面沒有數(shù)據(jù)的話就會把傳遞過來的boolean類型放到looper對象的參數(shù)中,然后設置到線程池里去運用。
getMainLooper方法,會鎖住looper類,然后返回當前正在使用的looper。
myLooper()方法,會從當前的threadlocal獲取內(nèi)容并進行返回。
showSlowLog(long threshold, long measureStart, long measureEnd,String what, Message msg)方法,傳遞過來的參數(shù)如果還在倒計時,那么就打印log并返回為true,打印的log內(nèi)容見下圖:
myLooper()方法,會獲取當前threadllocal里面的內(nèi)容進行return。
myQueue()方法,執(zhí)行mylooper方法獲取其mQueue變量進行retun。
Looper(boolean quitAllowed)方法,實例化的時候會把傳遞過來參數(shù)作為實例化MessageQueue的參數(shù),并且當前的線程會獲取當前的線程,表述的可能不太清晰看圖吧:
isCurrentThread()方法,該方法會判斷l(xiāng)ooper當前的sThread常量和Thread.currentThread()返回的變量是否相等(==)
setMessageLogging(@Nullable Printer printer)方法,會把傳遞過來的Printer 賦值給當前l(fā)ooper的mLogging變量。Printer 的用法還請再看相關介紹~
quit()方法,執(zhí)行l(wèi)ooper當前queue的quit(blooean)方法,傳遞false過去。
quitSafely()方法,同樣執(zhí)行queue的quit方法,但是會傳遞true過去,至于這個方法傳遞不同參數(shù)的含義請到queue分析當中去看。
getThread()方法,return looper當前的mThread。
getQueue()方法,return looper當前的mQueue。
dump(@NonNull Printer pw, @NonNull String prefix) 方法,會用傳遞過來的pw打印出prefix內(nèi)容,然后執(zhí)行mqueue.dump方法,該方法第三個參數(shù)為null。
dump(@NonNull Printer pw, @NonNull String prefix, Handler handler)方法,會用傳遞過來的pw打印出prefix內(nèi)容,然后執(zhí)行mqueue.dump方法,該方法第三個參數(shù)為傳遞過來的handler。具體執(zhí)行內(nèi)容也請看queue里面的dump方法。(該方法為hide,寫多了)
toString()方法,這個就看圖片吧。
prepareMainLooper()方法,會把false傳遞到要執(zhí)行的prepare方法中。然后synchronized-- looper類 判斷當前的looper是否為null,為null的話就走myLooper方法進行獲取,不為null則會拋出IllegalStateException。
loop方法內(nèi)容比較多,也需要結合代碼進行查看。先進行大概描述,然后再結合圖片里面的代碼進行查看。
looper.loop會先執(zhí)行myLooper方法獲取looper判斷是否為null。獲取當前l(fā)ooper的mQueue,進入到無限循環(huán)當中,獲取queue里面的message。如果message為null就return,不為null時就會獲取當前的observer,獲取當前message里面的相關時間和tag用來判斷message的執(zhí)行時間。把相關tag放到trace.tracebegin當中進行跟蹤。判斷當前observer是否為空不為空的話執(zhí)行相應方法,首先執(zhí)行messageDispatchStarting方法,在message.target執(zhí)行dispatchMessage之后執(zhí)行observer.messageDispatched方法,如果這個時候走到catch里面了,會執(zhí)行observer的dispatchingThrewException方法。trycatch最終都會跟蹤該消息。判斷時間打印出相應的log,最終會執(zhí)行message.recycleUnchecked()重置message 的內(nèi)容和Binder.clearCallingIdentity()方法清理標識。
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對外暴露的方法基本都已經(jīng)寫出。
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
本文標題:AndroidLooper用法及分析-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://www.rwnh.cn/article6/dcdoig.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供建站公司、外貿(mào)網(wǎng)站建設、軟件開發(fā)、網(wǎng)站設計、網(wǎng)站設計公司、網(wǎng)站營銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)