先看看一個例子:
1 private static Drawable sBackground; 2 3 @Override 4 protectedvoid onCreate(Bundle state){ 5 super.onCreate(state); 6 7 TextView label =newTextView(this); 8 label.setText("Leaks are bad"); 9 10 if(sBackground ==null){ 11 sBackground = getDrawable(R.drawable.large_bitmap); 12 } 13 label.setBackgroundDrawable(sBackground); 14 15 setContentView(label); 16 } 17
上面幾行代碼,內存泄露挺嚴重的。sBackground是一個 static 變量,在 label調用setBackgroundDrawable的時候,會調用sBackground的setCallback,所以在sBackground中就存在label的引用。
而,label中又存在Activity的引用,所以此Activity一直不會被回收,即使已經finish了。
如何避免:
- 使用applicationContext作為上下文,避免使用activity
- 設置Drawable的Callback為null
- 在Service或者Activity使用內部類盡量使用static類。例如:使用Handler
關於第3點,看個例子:
1 static class IncomingHandlerextendsHandler { 2 private final WeakReference<UDPListenerActivity> mActivity; 3 4 IncomingHandler(UDPListenerActivity activity) { 5 mService = newWeakReference < UDPListenerActivity > (activity); 6 } 7 8 @Override 9 public void handleMessage(Message msg) { 10 UDPListenerActivity activity = mActivity.get(); 11 if (activity != null) { 12 activity.handleMessage(msg); 13 } 14 } 15 }
我們知道,Message發出之后是存在MessageQueue中的,有些Message也不是馬上就被處理的。在Message存在一個 target,是Handler的一個引用,如果Message在Queue中存在的時間越長,就會導致Handler無法被回收。如果Handler是非靜態的,則會導致Activity或者Service不會被回收。
所以正確處理Handler等之類的內部類,應該采用上述代碼。
參考:
-----END-----