Handler寫法不當導致的記憶體洩漏
阿新 • • 發佈:2018-11-12
有強迫症的猿看到這個警告就會感覺彆扭,那麼這個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);