說說內存泄露那點事


先看看一個例子:

 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了。

如何避免:

  1. 使用applicationContext作為上下文,避免使用activity
  2. 設置Drawable的Callback為null
  3. 在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-----

 


免責聲明!

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



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