1. 程式人生 > >Handler寫法不當導致的記憶體洩漏

Handler寫法不當導致的記憶體洩漏

有強迫症的猿看到這個警告就會感覺彆扭,那麼這個This Handler class should be static or leaks might occur到底是啥意思呢,為什麼會有警告呢?下面就給大家解釋一下:在Java中,非靜態(non-static)內部和匿名類將會持有外部類的引用。相反,靜態的內部類不會持有外部類的引用,而上面的這個明顯是匿名內部類,如果Handler位於主執行緒,則使用的是主執行緒的Looper和MessageQueue,那麼每一個Message的target就是這個Handler,持有這個Handler的引用,假設這個時候GC要回收當前的Activity或者Service,但是由於Message太多處理不過來,或者Message延遲過大導致等待,那麼這個Handler則不會被回收,因為它被Message引用,而同時我們的Handler又是個內部類,持有外部Activity或者Service的引用,而且又不是static的,那麼外部Activity或者Service也不會被回收,所以就釋放不了啦,洩露啦。 使用弱引用之後,Handler和外部的Activity或者Service的引用性變低,就好像以前用鋼絲繩困在一起的,現在換棉線了,GC的時候就一定會回收掉弱引用包裝的物件。修改方法如下:

class MusicPlayerHandler extends Handler{
		private WeakReference<SnsMusicDetailActivity> mWeakReference;

		public MusicPlayerHandler(SnsMusicDetailActivity reference) {
			mWeakReference = new WeakReference<SnsMusicDetailActivity>(reference);
		}

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			SnsMusicDetailActivity reference = mWeakReference.get();
			if (reference == null) { // the referenced object has been cleared
				return;
			}
			switch (msg.what){
				case MusicPlayerTimer.MSG_WHAT_MUSIC_PLAYER_TIMER:
					if (!isPlay){
						SnsMusicDetailActivity.this.play_progress_time.setText("00:00");
						SnsMusicDetailActivity.this.detail_play_progress.setProgress(0);
						return;
					}
					long currentTime = (long) msg.obj;
					int progress = (int) (100*currentTime/mAllPlayTime);
					//進度條進度
					SnsMusicDetailActivity.this.detail_play_progress.setProgress(progress);
					//時間進度
					long  progressTime = currentTime/1000;
					int hour= (int) (progressTime/3600);
					int min= (int) ((progressTime%3600)/60);
					int sec= (int) ((progressTime%3600)%60);
					String minute =min>9?""+min:"0"+min;
					String second =sec>9?""+sec:"0"+sec;
					if (hour==0){
						SnsMusicDetailActivity.this.play_progress_time.setText(minute+":"+second);
					}else {
						String hourTime =hour>9?""+hour:"0"+hour;
						SnsMusicDetailActivity.this.play_progress_time.setText(hourTime+":"+minute+":"+second);
					}
					break;
			}
		}
	}

對於MusicPlayerHandler的建立也簡單,只要把當前Activity穿進去就行,例如:

MusicPlayerHandler mHandler =new MusicPlayerHandler(SnsMusicDetailActivity.this);