內部Handler類引起記憶體洩露
原文地址:http://blog.chengyunfeng.com/?p=468
如果您在Activity中定義了一個內部Handler類,如下程式碼:
public class MainActivity extends Activity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//TODO handle message...
}
};
@TargetApi(11)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler.sendMessageDelayed(Message.obtain(), 60000);
//just finish this activity
finish();
}
}
Read more: http://blog.chengyunfeng.com/?p=468#ixzz445wT2Gpw
然後執行Android Lint工具會有一個記憶體洩露警告:
This Handler class should be static or leaks might occur (com.example.ta.MainActivity.1)
Issue: Ensures that Handler classes do not hold on to a reference to an outer class
Id: HandlerLeakIn Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.
原因是:
- 當Android應用啟動的時候,會先建立一個應用主執行緒的Looper物件,Looper實現了一個簡單的訊息佇列,一個一個的處理裡面的Message物件。主執行緒Looper物件在整個應用生命週期中存在。
- 當在主執行緒中初始化Handler時,該Handler和Looper的訊息佇列關聯。傳送到訊息佇列的Message會引用傳送該訊息的Handler物件,這樣系統可以呼叫 Handler#handleMessage(Message) 來分發處理該訊息。
- 在Java中,非靜態(匿名)內部類會引用外部類物件。而靜態內部類不會引用外部類物件。
- 如果外部類是Activity,則會引起Activity洩露 。
當Activity finish後,延時訊息會繼續存在主執行緒訊息佇列中1分鐘,然後處理訊息。而該訊息引用了Activity的Handler物件,然後這個Handler又引用了這個Activity。這些引用物件會保持到該訊息被處理完,這樣就導致該Activity物件無法被回收,從而導致了上面說的 Activity洩露。
要修改該問題,只需要按照Lint提示的那樣,把Handler類定義為靜態即可,然後通過WeakReference 來保持外部的Activity物件。
private Handler mHandler = new MyHandler(this);
private static class MyHandler extends Handler{
private final WeakReference<Activity> mActivity;
public MyHandler(Activity activity) {
mActivity = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
System.out.println(msg);
if(mActivity.get() == null) {
return;
}
}
}
Read more: http://blog.chengyunfeng.com/?p=468#ixzz445wZB4mt
所以,當你在Activity中使用內部類的時候,需要時刻考慮您是否可以控制該內部類的生命週期,如果不可以,則最好定義為靜態內部類。
Read more: http://blog.chengyunfeng.com/?p=468#ixzz445vzsIoB
相關文章
- Android中Handler引起的記憶體洩露Android記憶體洩露
- Android 中 Handler 引起的記憶體洩露Android記憶體洩露
- 記憶體洩露引起的問題記憶體洩露
- android Handler導致的記憶體洩露Android記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- 記憶體洩露記憶體洩露
- js引起記憶體洩露的幾種情況分析JS記憶體洩露
- js記憶體洩露JS記憶體洩露
- JavaScript記憶體洩露JavaScript記憶體洩露
- 記憶體洩露嗎記憶體洩露
- Java字串的substring真的會引起記憶體洩露麼?Java字串記憶體洩露
- Android中使用Handler造成記憶體洩露的分析和解決Android記憶體洩露
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- WebView引起的記憶體洩漏WebView記憶體
- Android 多執行緒:你的 Handler 記憶體洩露 了嗎?Android執行緒記憶體洩露
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 實戰Go記憶體洩露Go記憶體洩露
- js記憶體洩露的原因JS記憶體洩露
- Java記憶體洩露的原因Java記憶體洩露
- JAVA 記憶體洩露的理解Java記憶體洩露
- IE中的記憶體洩露記憶體洩露
- 學習Java:記憶體洩露Java記憶體洩露
- 記一次Go websocket 專案記憶體洩露排查 + 使用Go pprof定位記憶體洩露GoWeb記憶體洩露
- Handler記憶體洩漏分析及解決記憶體
- Handler的使用、記憶體洩漏和解決記憶體
- Android 記憶體洩露詳解Android記憶體洩露
- 線上記憶體洩露定位--memleak工具記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- Android 檢測記憶體洩露Android記憶體洩露
- 如何處理 JavaScript 記憶體洩露JavaScript記憶體洩露
- leaks工具查詢記憶體洩露記憶體洩露
- MFC記憶體洩露與檢測記憶體洩露
- 如何定位和解決記憶體洩露記憶體洩露
- JavaScript中的記憶體洩露模式JavaScript記憶體洩露模式
- ThreaLocal記憶體洩露的問題記憶體洩露
- JVM與記憶體洩露問題JVM記憶體洩露
- 如何避免JavaScript的記憶體洩露及記憶體管理技巧JavaScript記憶體洩露