主線程建立的時候會默認建立Looper、HandlerThread則是內置Looper,除此以外其餘的線程建立時是不會建立Looper的,需手動創健線程本身的Looper。ide
子線程更新主線程建立的控件引起的錯誤:Only the original thread that created a view hierarchy can touch its views函數
默認狀況下Handler會與其被定義時所在線程的Looper綁定,好比,在主線程中定義,其是與主線程的Looper綁定。oop
HandlerThread實際上就是一個Thread,只不過它比普通的Thread多了一個Looper。Looper 和MessageQueue的關係:MessageQueue是Looper類的成員變量。主線程被建立以後會默認建立Looper,這個Looper是屬於主線程的,他會爲主線程建立MessageQueue消息循環隊列。spa
看具體代碼分析:線程
這段代碼會報錯,會提示說子線程不能更新主線程的控件,爲何?3d
首先建立名字叫「MyHandlerThread」的線程,這個階段同時也爲這個線程默認建立了Looper(消息循環器)、和MessageQueue(消息隊列)。對象
表示將Handler綁定到線程「MyHandlerThread」的Looper,讓Handler專門來處理Looper的消息blog
將實現Runnable的對象,做爲Message對象傳給線程「MyHandlerThread」的MessageQueue,當線程「MyHandlerThread」的Looper拿出這個消息的時候,發現這個消息是實現Runnable接口的類的對象,因而就會去掉用回調函數run(),其實就是把回調函數的代碼拿到線程「MyHandlerThread」裏來執行。繼承
若是建立一個子線程,你但願本身的子線程可以有本身的Looper、Handler、MessageQueue你有兩種方法,一種是像以前建立線程同樣,但要在重寫的run{}方法裏,爲線程建立Looper,這種方法比較麻煩,能夠直接使用HandlerThread,不必在重寫run{},由於HandlerThread的run()方法其中涉及到Looper的建立和啓動,Looper.loop()一執行就會進入死循環,就算你重寫HandlerThread的run()也沒用,那裏的代碼沒機會被執行,由於此時正在執行Looper.loop()這個死循環。接口
繼承Thread重寫run()沒有調用super.run(),HandlerThread重寫時就有:
Spuer.run()系統本身自動加的,HandlerThread和Thread不大同樣,他有本身的Looper,而HandlerThread的run()方法就是來建立Looper的,系統要確保這個函數會被執行,因此要在覆蓋他的函數裏添加super.run()來調用HandlerThread的run()方法。
爲何在子線程內部建立Handler會報錯:那是由於子線程沒有Looper,你能夠不要將Handler對象放在子線程,能夠放在主線程,由於主線程的Looper是默認建立的,這樣借用主線程的Handler和Looper來處理消息。或者你也能夠爲子線程建立Looper,這樣子線程就有一套本身的Looper、MessageQueue、Handler,就能夠來在子線程內處理消息,建立子線程的Looper: Looper looper = Looper.myLooper ( );