按照android handler詳解分析的原理我們可以知道,在主線程中創建handle對象的時候,主線程默認創建了一個loop對象使用threalocal函數將loop對象和主線程綁定。
我們能不能在子線程中創建一個loop對象和子線程綁定了實際上是可以的
這樣我們就在子線程中創建了一個looper對象,將looper對象和子線程綁定了,在子線程中執行Loop.loop()函數的內部是開啟了一個死循環對消息隊列中的消息進行遍歷,所以子線程是永遠不會退出的。
當我們在主線程中調用獲得subHandler對象就可以給子線程發送了消息了
子線程收到了消息之后會在handlMessage中彈出一個Toast
這里為啥能夠在子線程中彈出Toast了,因為在子線程中存在looper對象和該子線程綁定。正常情況下之所以只能在主線程中彈出toast,是因為主線程會有一個默認的looper對象和主線程綁定。現在我們在子線程中創建了一個looper對象,所以就能夠在子線程中彈出一個toast
總結:
如果一個線程要處理消息,那么它必須擁有自己的Looper,很明顯的一點就是,我們要在子線程中調用Looper.prepare() 為一個線程開啟一個消息循環,默認情況下Android中新誕生的線程是沒有開啟消息循環的。(主線程除外,主線程系統會自動為其創建Looper對象,開啟消息循環。) Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。 然后通過Looper.loop() 讓Looper開始工作,從消息隊列里取消息,處理消息。
上面的代碼存在內存泄露,為啥了因為在線程中Loop.loop()方法內部是開啟了一個死循環來對消息隊列進行遍歷,所以即使activity退出了,該線程還是不會退出,線程里面toast存在MainActivity的引用,就會導致activity退出了,但是activity在線程中的引用還存在,導致內存泄露
如何解決了,我們應該在activity的onDestory中退出的時候,停止死循環變量消息隊列,可以調用looper對象的quit函數,所以首先我們需要得到該looper對象
其次在activity的onDestory中調用quit函數
是不是相當的經典