![](/img/trans.png)
[英]Why do I get a “Can't create handler inside a thread that has not called Looper.prepare()” with android.os.CountDownTimer?
[英]Android: Why can't I create a handler in new thread
我在新線程中創建處理程序時遇到問題。 這是我的代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler();
}
}).start();
}
但它引起了錯誤! 有人可以向我解釋一下嗎? 非常感謝!
以下是我的錯誤的詳細信息:
09-17 18:05:29.484: E/AndroidRuntime(810): FATAL EXCEPTION: Thread-75
09-17 18:05:29.484: E/AndroidRuntime(810): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-17 18:05:29.484: E/AndroidRuntime(810): at android.os.Handler.<init>(Handler.java:197)
09-17 18:05:29.484: E/AndroidRuntime(810): at android.os.Handler.<init>(Handler.java:111)
09-17 18:05:29.484: E/AndroidRuntime(810): at com.example.handler.MainActivity$1.run(MainActivity.java:57)
09-17 18:05:29.484: E/AndroidRuntime(810): at java.lang.Thread.run(Thread.java:856)
你也可以像這樣使用HandlerThread
:
HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
HandlerThread
有一個與它們相關聯的Looper
,所以這不會引發異常。
Thread的lifecycle
在run方法返回后立即完成。 但是由於您在此thread
中創建了一個Handler
,因此Handler需要運行該線程才能接收消息並處理它們。
因此,為此,run方法不應該退出。 因此,您需要一個Looper無限期地等待並處理到達Handler的消息。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
}
}).start();
簡答:因為您嘗試連接處理程序的線程沒有彎針。 所以Handler類的構造函數拋出異常。 您可以使用HandlerThread類,這只是Android框架提供的一個方便的類。
請閱讀以下內容,了解引擎蓋下發生的事情。
讓我們首先嘗試單獨討論所有部分。
一個。 線程只是一個執行流程。 默認情況下,線程只是執行其runnable(如果提供)或調用其run方法。 在調用新的Thread.start()時。 當run方法執行run(){----}中寫入的所有語句時,線程就會死掉並且Gc'd。
灣 Android中有一個Looper的概念。 這基本上使線程成為阻塞線程。 簡單地說就是不讓線程死掉。 它進入阻塞狀態並等待更多消息再次恢復執行。
下面是你如何設置一個阻塞線程,即一個帶有looper的線程。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
Looper.loop();
}
}).start();
這里創建了一個線程,它不僅在執行Looper.loop()語句后死掉。 相反,它循環並進入阻塞狀態。 現在你必須要問阻塞狀態是什么意思,線程將如何脫離阻塞狀態? 我現在如何最終發布這個帖子? 這就是Handler的用武之地
一個。 它總是將自身附加到線程的Looper上,在該線程上創建其實例。
灣 然后它處理它附加的線程的那些消息。
將線程和處理程序放在一起。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
handler = new Handler();
Looper.loop();
}
}).start();
一個。 處理程序如何附加到這個新創建的線程。 灣 該線程被設置為阻塞循環線程。 所以這不會死。
現在,我們可以1.在此處理程序上發送消息。 2.在此處理程序上發布runnable。
它們都將在附加的線程上執行。
您可以選擇擴展Handler類並實現方法handleMessage(Message msg)。 或者您只是在處理程序類的構造函數中提供Handler.Callback的實現。 無論哪種方式,都會在附加的線程上調用handleMessage(Messages msg)。
要退出線程,您可以發送特定類型的消息類型,並在收到該消息后,您只需調用Looper.myLooper()。quit()
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
if(msg.what == -1){
Looper.myLooper().quit();
}
}
};
Looper.loop();
}
}
我希望它有助於理解整體概念。
Handler需要在Looper線程中初始化,或者給它一個Looper。
根據您的要求,您可以將線程設置為Looper,如下所示:
new Thread(new Runnable() {
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}).start();
由於Looper位於后台線程中,因此無法更新UI。 您可以替代地從另一個線程向Handler提供一個Looper - 在此示例中,Handler可用於更新UI:
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper());
}
}).start();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.