Handler用于處理和從隊列MessageQueue中得到Message。1般我們要重寫Handler的handleMessage(Message msg){}方法來處理,以下代碼:
這個時候Handler會被Android SDK中Lint工具檢查正告你(左側那個黃色燈泡+嘆號):This Handler class should be static or leaks might occur 。
This Handler class should be static:
(知識點1)為何靜態內部類可以解決這個問題呢?或說靜態內部類和非靜態內部類的區分是甚么?
舉例:class A{int a; static int b class B{} static class C{} } (A是外部類,B非靜態內部類,C靜態內部類,a普通字段,b靜態字段)
1)B非靜態內部類:
可以訪問A.a和A.b,也就是外部的屬性都能方位。由于B隱式的持有A類對象的援用,相當于A的屬性
2)C靜態內部類:
C只可以訪問A.b,不可以方位A.a。為何?由于C不含有A的援用,它和A類是同1個級別,只不過寫到了A類的內部。
本例緣由:
Handler匿名內部類,隱式的持有了外部類Activity的援用(這就是為何你能在handleMessage()中調用MainActivity中TextView等的屬性)。--->而以后調
在100秒后message被履行,這期間message被放在MessageQueue中,MessageQueue在Looper中,Looper是線程的本地變量。
也就是說MainActivity即便生命周期走完了也不會垃圾回收,為何?由于Java的垃圾回收機制,就是看1個對象有無被援用(從線程中的主要對象開始,對象之間的援用構成網狀結構,如果有類的對象不在這張網上,就證明它沒被援用。這就是數據結構中圖的遍歷,甚么連通子圖,非連通子圖)。而本文中1個MainActivity被Handler持有援用,Handler被Message持有援用,Message被MessageQueue持有援用,MessageQueue被Looper持有援用,Looper為線程本地變量,線程不被摧毀,它就不會被燒毀。
所以即使用戶已切換、退出到別的Activity,MainActivity占有的內存仍舊不會被釋放。
打破援用鏈:
1.Message在100秒后被處理,以后回收Message,然后回收MainActivity。(所以是實際上,你只要不發很長時間的Message也不會有甚么問題)
2.使Handler不持有MainActivity的援用,用弱援用WeakReference:(簡單講,就是只有WeakReference援用的對象,垃圾回收將回收該對象,以后再另寫1篇援用的文章吧)