Android學習-Handler內存泄漏

2016/08/20java

最近輕微強迫症又犯了,看着編譯器上的那些帶有黃色感嘆號警告就十分難受,因而就下定決心清除我能看到的全部黃色感嘆號,通常我不會用像圖1中系統提示那些處理方法,android


我以爲那是在欺騙本身,可能在處理這些警告上有些費時,可是無論怎樣,本身開心就好,得意.前幾天在寫一個線程實例的時候瀏覽器

用到了Handler 來傳遞數據,我以前都是像圖2那樣寫的,圖2上已然出現了一個傲嬌的黃色感嘆號,警告的內容是 This Handler class should be static or leaks might occur (com.example.ndktest.MainActivity.1) 我把我那蹩腳英語能力和有道詞典有機統一的結合以後,籠統的明白的這句話的意思是:這個Handler 類應該是靜態的,不然可能引發內存泄漏問題,在我很有成就感的品味被我翻譯出來的譯文的同時,我又開始蒙圈了,究竟是什麼緣由出現這樣奇葩的警告呢,我以前都是這麼寫的,歷來都沒有出現過內存泄漏的現象,那這個發生內存泄漏的機率豈不是很低,知其然而不知其因此然,苦惱數微秒以後,我就打開了瀏覽器,開始刨根問底,許久以後有了些收貨.先附上個人測試代碼ide

public class MainActivity extends Activity {

	public TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		tv = (TextView) findViewById(R.id.tv);
	}

	Handler handler = new Handler() {

		public void handleMessage(android.os.Message msg) {

			tv.setText("我收到了message");

		};
	};
}


根據代碼能夠看出 handler 是一個內部類,內部類分兩種,一種是普通內部類,也就是像上面代碼裏handler這個類那樣,另外一種是加static關鍵字的靜態內部類,就是那段警告所說的改正後的類的類型.普通內部類隱含保存了外部類的引用,靜態內部類就不是這樣了,靜態內部類只能訪問外部類的靜態成員.那這跟內存泄漏有什麼關係呢,其實思考到這裏,答案就已經很明朗了,關鍵點就在於普通內部類隱含保存了外部類的引用,若是我在上面代碼的oncreate函數裏添加finish()方法以後,在運行到finish()後,本應該進行對MainActivity 垃圾回收的,可是因爲handler內部類有對MainActivity  的引用,因此是MainActivity 對象是不會被回收的,這就形成了內存的泄漏.要解決這樣的問題,就要用到弱引用,在垃圾回收器線程掃描它所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,就會回收它的內存,不會考慮內存的充足與否。這樣就解決了內存泄漏問題函數

改後的代碼測試

public class MainActivity extends Activity {

	public TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		tv = (TextView) findViewById(R.id.tv);
	}

	// Handler handler = new Handler() {
	//
	// public void handleMessage(android.os.Message msg) {
	//
	// tv.setText("我收到了message");
	//
	// };
	// };

	MyHandler handler = new MyHandler(this);

	static class MyHandler extends Handler {
		WeakReference<MainActivity> mActivity;

		public MyHandler(MainActivity activity) {

			mActivity = new WeakReference<MainActivity>(activity);
		}

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			MainActivity a = mActivity.get();

			if (a != null) {
				a.tv.setText("我收到了message");
			}

		}

	}

}
相關文章
相關標籤/搜索