Android Handler之使用小結


在android開發中,使用Handler處理各種消息機制。

Handler用於處理和從隊列MessageQueue中得到Message。一般我們要重寫Handler的handleMessage(Message msg){}方法來處理,如下代碼:

使用內部類的方式實現,官方是不建議這樣寫的。

public class MainActivity extends Activity {
    
	Handler mHandler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				//處理各種接受消息邏輯
				break;

			default:
				break;
			}
		};
	};
}

  

這個時候Handler會被Android SDK中Lint工具檢查警告你(左邊那個黃色燈泡+嘆號):This Handler class should be static or leaks might occur 。

 

為什么靜態內部類可以解決這個問題呢?或者說靜態內部類和非靜態內部類的區別是什么?

舉例: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類是同一個級別,只不過寫到了A類的內部。

link的警告原因:

Handler匿名內部類,隱式的持有了外部類Activity的引用。

 

Message message = normalHandler.obtainMessage();
normalHandler.sendMessageAtTime(message , 100*1000);


得到的message中又含有這個Handler的引用(可以看源碼)。

 

在100秒后message被執行,這期間message被放在MessageQueue中,MessageQueue在Looper中,Looper是線程的本地變量。

也就是說MainActivity即使生命周期走完了也不會垃圾回收,為什么?因為Java的垃圾回收機制,就是看一個對象有沒有被引用(從線程中的主要對象開始,對象之間的引用形成網狀結構,如果有類的對象不在這張網上,就證明它沒被引用。這就是數據結構中圖的遍歷,什么連通子圖,非連通子圖)。而本文中一個MainActivity被Handler持有引用,Handler被Message持有引用,Message被MessageQueue持有引用,MessageQueue被Looper持有引用,Looper為線程本地變量,線程不被摧毀,它就不會被銷毀。

所以即便用戶已經切換、退出到別的Activity,MainActivity占有的內存仍舊不會被釋放。

 

解決方案:

打破引用鏈?

1.Message在100秒后被處理,之后回收Message,然后回收MainActivity。(所以是實際上,你只要不發很長時間的Message也不會有什么問題)

2.使Handler不持有MainActivity的引用,用弱引用WeakReference:(簡單講,就是只有WeakReference引用的對象,垃圾回收將回收該對象)

MyHandler handler = new MyHandler(this);

	public static class MyHandler extends Handler {
		private WeakReference<MainActivity> reference;

		public MyHandler(MainActivity activity) {
			reference = new WeakReference<MainActivity>(activity);
		}

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				//處理接受消息邏輯
				break;

			default:
				break;
			}
		}
	}

  

為何Android界面更新,Handler作為匿名內部類來實現handlerMessage方法 

最重要的不是線程安全問題,而是android組件的監聽方法中只能訪問final 的屬性,所以是無法修改的,只能把它交給handler處理。不能在非UI線程,繪制渲染潔面。

為何需要Handler而不用Thread。除了消息模型是UI框架的經典模式外,還涉及到UI組件不允許跨線程訪問的限制。無論是.NET也好,swing也好,android也好,不允許在非UI線程中操作這一點都一樣。
Handler便是android框架中異步線程代碼到達同步線程的官方通道。從另一個角度說,這種基於消息模型的通信模式有時也很有用。相關的例子有IntentService,HandlerThread等。

 

 

轉自:http://www.bkjia.com/Androidjc/904357.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM