欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android開發(fā)中Looper.prepare()和Looper.loop()

 更新時間:2016年11月12日 11:18:55   作者:屌絲迷途  
Looper用于封裝了android線程中的消息循環(huán),默認情況下一個線程是不存在消息循環(huán)(message loop)的,具體調(diào)用方法大家可以通過本文學習

什么時候需要 Looper

  Looper用于封裝了android線程中的消息循環(huán),默認情況下一個線程是不存在消息循環(huán)(message loop)的,需要調(diào)用Looper.prepare()來給線程創(chuàng)建一個消息循環(huán),調(diào)用Looper.loop()來使消息循環(huán)起作用,使用Looper.prepare()和Looper.loop()創(chuàng)建了消息隊列就可以讓消息處理在該線程中完成。

使用Looper需要注意什么

  寫在Looper.loop()之后的代碼不會被立即執(zhí)行,當調(diào)用后mHandler.getLooper().quit()后,loop才會中止,其后的代碼才能得以運行。Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。

比如下面的代碼,只要調(diào)用了getLooper().quit()后代碼2才會執(zhí)行。

class LooperThread extends Thread
{
4 public void run() 
{
Looper.prepare();
//代碼1....
Looper.loop();
//代碼2....
} 
}

警惕線程未終止造成的內(nèi)存泄露;譬如在Activity中關(guān)聯(lián)了一個生命周期超過Activity的Thread,在退出Activity時切記結(jié)束線程。一個典型的例子就是HandlerThread的run方法是一個死循環(huán),它不會自己結(jié)束,線程的生命周期超過了Activity生命周期,我們必須手動在Activity的銷毀方法中中調(diào)運thread.getLooper().quit();才不會泄露。

Looper與Activity

Activity的MainUI線程默認是有消息隊列的。所以在Activity中新建Handler時,不需要先調(diào)用Looper.prepare()

主線程中的Looper.loop()一直無限循環(huán)為什么不會造成ANR

ActivityThread.java 是主線程入口的類,這里你可以看到寫Java程序中司空見慣的main方法,而main方法正是整個Java程序的入口。

ActivityThread源碼

public static final void main(String[] args) {
...
//創(chuàng)建Looper和MessageQueue
Looper.prepareMainLooper();
...
//輪詢器開始輪詢
Looper.loop();
...
}

Looper.loop()方法

while (true) {
//取出消息隊列的消息,可能會阻塞
Message msg = queue.next(); // might block
...
//解析消息,分發(fā)消息
msg.target.dispatchMessage(msg);
...
}

ActivityThread的main方法主要就是做消息循環(huán),一旦退出消息循環(huán),那么你的應用也就退出了。那為什么這個死循環(huán)不會造成ANR異常呢?

因為Android 的是由事件驅(qū)動的,looper.loop() 不斷地接收事件、處理事件,每一個點擊觸摸或者說Activity的生命周期都是運行在 Looper.loop() 的控制之下,如果它停止了,應用也就停止了。只能是某一個消息或者說對消息的處理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。也就說我們的代碼其實就是在這個循環(huán)里面去執(zhí)行的,當然不會阻塞了。

handleMessage方法部分源碼

public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord) msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder) msg.obj, false, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder) msg.obj, true, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 1) != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...........
}
}

可以看見Activity的生命周期都是依靠主線程的Looper.loop,當收到不同Message時則采用相應措施。

如果某個消息處理時間過長,比如你在onCreate(),onResume()里面處理耗時操作,那么下一次的消息比如用戶的點擊事件不能處理了,整個循環(huán)就會產(chǎn)生卡頓,時間一長就成了ANR。

相關(guān)文章

最新評論