總結--3

主線程建立的時候會默認建立LooperHandlerThread則是內置Looper,除此以外其餘的線程建立時是不會建立Looper的,需手動創健線程本身的Looperide

子線程更新主線程建立的控件引起的錯誤:Only the original thread that created a view hierarchy can touch its views函數

默認狀況下Handler會與其被定義時所在線程的Looper綁定,好比,在主線程中定義,其是與主線程的Looper綁定。oop

HandlerThread實際上就一個Thread,只不過它比普通的Thread多了一個LooperLooper MessageQueue的關係:MessageQueueLooper類的成員變量。主線程被建立以後會默認建立Looper,這個Looper是屬於主線程的,他會爲主線程建立MessageQueue消息循環隊列。spa

看具體代碼分析:線程

wKiom1Nw4DLTdlnGAAGoyJar7Xk458.jpg

這段代碼會報錯,會提示說子線程不能更新主線程的控件,爲何?3d


wKiom1Nw4MHRVNYeAABt5kpwY6c857.jpg

首先建立名字叫「MyHandlerThread」的線程,這個階段同時也爲這個線程默認建立了Looper(消息循環器)、和MessageQueue(消息隊列)。對象

wKiom1Nw4SrjmBZJAAAxxoLctfM364.jpg

表示將Handler綁定到線程MyHandlerThreadLooper,讓Handler專門來處理Looper的消息blog


wKiom1Nw4VWztcldAAEX9KdUyT4378.jpg

將實現Runnable的對象,做爲Message對象傳給線程MyHandlerThreadMessageQueue,當線程MyHandlerThreadLooper拿出這個消息的時候,發現這個消息是實現Runnable接口的類的對象,因而就會去掉用回調函數run(),其實就是把回調函數的代碼拿到線程MyHandlerThread」裏來執行。繼承

若是建立一個子線程,你但願本身的子線程可以有本身的LooperHandlerMessageQueue你有兩種方法,一種是像以前建立線程同樣,但要在重寫的run{}方法裏,爲線程建立Looper,這種方法比較麻煩,能夠直接使用HandlerThread,不必在重寫run{},由於HandlerThreadrun()方法其中涉及到Looper的建立和啓動,Looper.loop()一執行就會進入死循環,就算你重寫HandlerThreadrun()也沒用,那裏的代碼沒機會被執行,由於此時正在執行Looper.loop()這個死循環。接口

繼承Thread重寫run()沒有調用super.run()HandlerThread重寫時就有:

Spuer.run()系統本身自動加的,HandlerThreadThread不大同樣,他有本身的Looper,而HandlerThreadrun()方法就是來建立Looper的,系統要確保這個函數會被執行,因此要在覆蓋他的函數裏添加super.run()來調用HandlerThreadrun()方法。

爲何在子線程內部建立Handler會報錯:那是由於子線程沒有Looper,你能夠不要將Handler對象放在子線程,能夠放在主線程,由於主線程的Looper是默認建立的,這樣借用主線程的HandlerLooper來處理消息。或者你也能夠爲子線程建立Looper,這樣子線程就有一套本身的LooperMessageQueueHandler,就能夠來在子線程內處理消息,建立子線程的Looper:  Looper  looper  = Looper.myLooper ( );

相關文章
相關標籤/搜索